如何使用Moq创建私有依赖方法设置



我有以下Controller接口:

public interface IInformationController
{
string GetStoredInformation();
string GetInformation();
}

控制器类别如下:

public class InformationController : ControllerBase, IInformationController
{
private InformationProvider1 InformationProvider1;
private InformationProvider2 InformationProvider2;
private IBasicRepository repository;
public InformationController(IBasicRepository basicRepository)  
=> repository = basicRepository;
public string GetStoredInformation()
=> repository.GetStoredInformation();
public string GetInformation()
=> $"Information is {informationProvider1.GetInformationHeader()}, Information detail is {informationProvider2.GetInformationDetail()}";

}

我打算用xUnit和MoqInformationController创建一个单元测试。

这是我的测试课:

public class InformationControllerTest
{
public InformationControllerTest()
{
repositoryMock = new Mock<IBasicRepository>();
repositoryMock.Setup(repository => repository.GetStoredInformation()).Returns("Stored information");
SUT = new InformationController(repositoryMock.Object);
}
[Fact]
public void GetStoredInformation_Returns_Stored_Information()
{
string result = SUT.GetStoredInformation();
Assert.Equal("Stored information", result);
}
[Fact]
public void GetInformation_Returns_Valid_Information()
{
string result = SUT.GetInformation(); //TODO: how to avoid the usage of actual provider implementations?
Assert.Equal("Information is Header1, Information detail is Detail1", result);
}
}

正如你所看到的,有私人供应商。不幸的是,它们是外部依赖项,不容易通过依赖项注入引入。

我该如何嘲笑他们的实际通话?我应该模拟控制器方法吗(哪个imho应该使测试实际控制器的过程无效(?我应该尝试通过依赖项注入获得它们吗?

单元测试暴露了当前设计的缺点,它与外部依赖项或实现问题紧密耦合。

应将依赖项显式注入其依赖项

方法和类应该显式地要求(通常通过方法参数或构造函数参数(它们需要的任何协作对象才能正常工作。

引用显式依赖项原则

public class InformationController : ControllerBase, IInformationController {
private IInformationProvider1 informationProvider1;
private IInformationProvider2 informationProvider2;
private IBasicRepository repository;
public InformationController(IBasicRepository basicRepository,
IInformationProvider1 informationProvider1, 
IInformationProvider2 informationProvider2) {
repository = basicRepository;
this.informationProvider1 = informationProvider1;
this.informationProvider2 = informationProvider2
}
public string GetStoredInformation()
=> repository.GetStoredInformation();
public string GetInformation()
=> $"Information is {informationProvider1.GetInformationHeader()}, Information detail is {informationProvider2.GetInformationDetail()}";

//...
}

为这些外部依赖项创建抽象和实现,然后将它们注册到DI容器中,以便在运行时解析并正确地提供给控制器。这将使它们也能够在实际实现中进行隔离测试,而不会产生不希望的副作用。

最新更新