2

我正在尝试学习DI &嘲笑,Unity和NSubstitute。我也使用从这个问题采取的automocking扩展:Is this possible with Unity (Instead of Castle Windsor)?NSubstitute和Unity

在我的单元测试下面,我试图从我的方法Add()中设置NSubstitute返回值10。但是,通过控制器调用进行调试时,分配的值是默认的0,而不是预期的10.代理似乎不会拦截方法调用。

我怀疑这是由于没有正确注册我的类型/容器引起的,任何人都能指出我正确的方向?

[TestFixture] 
public class ApplicationControllerTests 
{ 
    private IUnityContainer _container; 
    private ApplicationController _controller; 
    private ISampleService _sampleService; 

    [SetUp] 
    public void SetUp() 
    { 
     _container = new UnityContainer().AddExtension(new AutoMockingContainerExtension()); 
     _controller = _container.Resolve<ApplicationController>(); 
     _sampleService = _container.Resolve<ISampleService>(); 
    } 

    [Test] 
    public void TestSampleService() 
    { 
     // This line is not working 
     _sampleService.Add(Arg.Any<int>(), Arg.Any<int>()).Returns(10); 

     var result = _controller.Index(); 

     _sampleService.Received().Add(Arg.Any<int>(), Arg.Any<int>()); 
    } 
} 

public class AutoMockingContainerExtension : UnityContainerExtension 
{ 
    protected override void Initialize() 
    { 
     var strategy = new AutoMockingBuilderStrategy(Container); 

     Context.Strategies.Add(strategy, UnityBuildStage.PreCreation); 
    } 

    class AutoMockingBuilderStrategy : BuilderStrategy 
    { 
     private readonly IUnityContainer _container; 

     public AutoMockingBuilderStrategy(IUnityContainer container) 
     { 
      _container = container; 
     } 

     public override void PreBuildUp(IBuilderContext context) 
     { 
      var key = context.OriginalBuildKey; 

      if (key.Type.IsInterface && !_container.IsRegistered(key.Type)) 
       context.Existing = CreateSubstitute(key.Type); 
     } 

     private static object CreateSubstitute(Type type) 
     { 
      return Substitute.For(new[] { type }, null); 
     } 
    } 
} 

我的控制器代码

public class ApplicationController : BaseController 
{ 
    private readonly ISampleService _sampleService; 

    public ApplicationController(ISampleService sampleService) 
    { 
     _sampleService = sampleService; 
    } 

    public ActionResult Index() 
    { 
     var result = _sampleService.Add(2, 3); 

     // result is 0, expected 10 ?? 

     return View(); 
    } 
} 

public interface ISampleService 
{ 
    int Add(int first, int second); 
} 

public class SampleService : ISampleService 
{ 
    public int Add(int first, int second) 
    { 
     return first + second; 
    } 
} 

回答

4

其实Tormod是正确的问题是,AutoMockingBuilderStrategy每次都返回不同的模拟实例有人请求时一个ISampleService形成容器。

所以在我original implementationAutoMockingBuilderStrategy不存储创建的嘲笑了一个错误:

这里有一个固定的版本:

public class AutoMockingContainerExtension : UnityContainerExtension 
{ 
    protected override void Initialize() 
    { 
     var strategy = new AutoMockingBuilderStrategy(Container); 

     Context.Strategies.Add(strategy, UnityBuildStage.PreCreation); 
    } 

    class AutoMockingBuilderStrategy : BuilderStrategy 
    { 
     private readonly IUnityContainer container; 
     private readonly Dictionary<Type, object> substitutes 
      = new Dictionary<Type, object>(); 

     public AutoMockingBuilderStrategy(IUnityContainer container) 
     { 
      this.container = container; 
     } 

     public override void PreBuildUp(IBuilderContext context) 
     { 
      var key = context.OriginalBuildKey; 

      if (key.Type.IsInterface && !container.IsRegistered(key.Type)) 
      { 
       context.Existing = GetOrCreateSubstitute(key.Type); 
       context.BuildComplete = true; 
      } 
     } 

     private object GetOrCreateSubstitute(Type type) 
     { 
      if (substitutes.ContainsKey(type)) 
       return substitutes[type]; 

      var substitute = Substitute.For(new[] {type}, null); 

      substitutes.Add(type, substitute); 

      return substitute; 
     } 
    } 
} 
+0

伟大的作品,谢谢 – Longball27

1

我怀疑你是在处理ISampleService的两种不同的情况下,在第2和分别设置3个,创建。 你能,测试,使_sampleServie领域的公共和第三设置()线试

_sampleService = _controller._sampleService;