我正在一个非常大的现有代码库中工作,我很难完全重构
MyTestFixture
。测试设置如下:
MyTestFixture.cs
public class MyTestFixture: IDisposable
{
IWebHost host;
public MyTestFixture()
{
this.host = CreateWebHost();
}
public CreateWebHost()
{
return new WebHostBuilder()
.ConfigureServices()
.Build();
}
}
MyTest1.cs
public class MyTest1 : IClassFixture<MyTestFixture>
{
MyTestFixture testFixture;
public MyTest1(MyTestFixture testFixture)
{
this.testFixture = testFixture;
}
}
在某些情况下,我需要模拟网络主机中的一项服务。我需要一个完整的 E2E,并且模拟所有单独的组件太困难了,我真的只想要一个完整的 E2E 运行,其中模拟一件小事情。我正在尝试找出将模拟服务注入网络主机的最佳方法。
我发现我可以做类似
this.testFixture.host.Services.GetRequiredService<ISomeService>();
的事情,但我没有看到任何添加服务的方法。有什么办法可以做到吗?
我的替代解决方案是向 MyTestFixture 添加一个新的虚拟属性,
Mocks
这是一个对象列表。我在 CreateWebHost
期间将对象列表注入到服务中。然后在 MyTest1
中,我创建一个继承自 MyTestFixture
并覆盖 Mocks
的新夹具。但这有点混乱,因为我没有找到在不搜索完整列表的情况下检索实际测试用例中的模拟的好方法。
public class OverrideClass : MyTestFixture
{
public OverrideClass(): Base(){}
public override List<Object> Mocks { get; set; } = new List<Object>()
{
A.Fake<ISomeService1>(),
A.Fake<ISomeService2>(),
}
}
public class MyTest1 : IClassFixture<OverrideClass>
...
我做了类似的事情,但在派生类可以覆盖的基类中使用
Action<IServiceCollection>
。然后在创建测试服务器时调用该委托:
class TestBaseClass {
protected Action<IServiceCollection>? ConfigureAdditionalTestServices { get; set; }
// Register the creation of the test server as factory method
// so that derived test classes can set-up fake services before
// creation
Fixture.Register(() =>
new WebApplicationFactory<TProgram>()
.WithWebHostBuilder(builder => {
builder.ConfigureTestServices(services => {
// Give tests a chance to add specific services
ConfigureAdditionalTestServices?.Invoke(services);
});
})
只要派生测试类在解析测试服务器的实例之前设置委托,就会执行委托并注册特定于测试的服务。
这意味着您只需在每次测试时注册要替换的服务即可。所有其他服务都使用适当的默认值。
当您需要注册工厂方法而不仅仅是实例时,使用委托方法而不是要注册的对象的通用列表可以提供更多功能。