2017-08-14 51 views
0

对不起,我没有太多的代码可供分享,因为我不确定这将如何工作。如何将测试项目中的依赖项传递给DryIoc中的具体实现

我有一个名为API.Tests的测试项目,我正在为API项目中的NewsController编写测试。我不知道如何将测试依赖项传递给API,因为它是单向引用。

NewsController

private IGetNews _getNews; 
    private IAddNews _addNews; 
    private ILoggingService _log; 

    public NewsController() 
    { 
     _getNews = RegisterDependencies.container.Resolve<IGetNews>(); 
     _addNews = RegisterDependencies.container.Resolve<IAddNews>(); 
     _log = RegisterDependencies.container.Resolve<ILoggingService>(); 
    } 

回答

1

您当前的代码是使用一个服务定位器的反模式。这使得控制器与这些依赖关系紧密耦合,难以独立测试。你需要反转这些依赖关系。 (即:依赖倒置)

重构控制器以通过构造函数注入来使用显式依赖关系。

public class NewsController { 
    private readonly IGetNews getNews; 
    private readonly IAddNews addNews; 
    private readonly ILoggingService log; 

    public NewsController(IGetNews getNews, IAddNews addNews, ILoggingService log) { 
     this.getNews = getNews; 
     this.addNews = addNews; 
     this.log = log; 
    } 

    //...other code 
} 

进行单元测试,你现在可以模拟和注入的依赖关系到被测对象。下面的示例使用一个模拟框架(MOQ)嘲笑的依赖,并将它们注入主题下测试

public void ExampleNewsControllerTest() { 
    //Arrange 
    var getNews = Mock.Of<IGetNews>(); 
    var addNews = Mock.Of<IAddNews>(); 
    var log = Mock.Of<ILoggingService>(); 

    var subject = new NewsController(getNews, addNews, log); 

    //Act 
    //...exercise the method under test 
    subject.SomeAction(); 

    //Assert 
    //...assert that the subject behaves as expected. 

} 

将配置的依赖关系,以适应测试用例/场景。

+0

是的,这是做它的经典方式正是我以前用的,但问题是我怎么告诉DryIoC在API项目中使用不同的注册依赖从API.Tests项目中,因为测试的实施具体的类是在API.Tests项目中? 我应该能够简单地告诉DryIoc“嘿解决这个实施IGetNews,而不是”,而不必通过的东西,并不需要被嘲笑一个模拟。 –

+0

我还应该提到这是一个Web API控制器,所以它必须有一个空白的构造函数。 –

+1

@ChristopherJohnson,Web API控制器不必**必须有空白的构造函数**。这是一个默认的误导性错误消息,框架引发了尝试初始化控制器时发生的任何错误。您需要阅读框架,并且还需要检查您的设计,因为您已经发现,由于糟糕的设计选择而难以测试。你所呼叫DI模式实际上是服务定位器ANIT模式。 – Nkosi

相关问题