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;