[英]In a dotnet 5 web api project, how do I get the instance of a singleton service in a test method?
I'm integration testing my asp.net 5 web apis.我正在集成测试我的 asp.net 5 web api。 In my test methods I want to get a reference to the instance a of faked service so I can customise the service's behaviour for my tests.
在我的测试方法中,我想获得对伪造服务实例 a 的引用,以便我可以为我的测试自定义服务的行为。
In the app, the service is scoped as singleton.在应用程序中,服务范围为 singleton。
//in ConfigureServices in Startup.cs
services.AddSingleton<IYbNewProjectsService, YbNewProjectsService>();
In my test project, I set up my client and server in my TestFixture class, and save a reference to the ServiceProvider, returned to me by the services.BuildServiceProvider() call...在我的测试项目中,我在我的 TestFixture class 中设置了我的客户端和服务器,并保存了对 ServiceProvider 的引用,由 services.BuildServiceProvider() 调用返回给我......
private void SetupClient()
{
Client = Factory.WithWebHostBuilder(builder =>
{
builder.ConfigureTestServices(services =>
{
services.Remove<IYbNewProjectsService>();
services.AddSingleton<IYbNewProjectsService, FakeYbNewProjetsService>();
});
builder.ConfigureServices(services =>
{
ServiceProvider = services.BuildServiceProvider();
});
})
.CreateClient(new WebApplicationFactoryClientOptions
{
AllowAutoRedirect = false
});
}
I know it's working, because in my tests, when I do...我知道它在工作,因为在我的测试中,当我做...
// ServiceProvider is inherited from TestFixture, so it's the same as above.
var fakeYbService = (FakeYbNewProjectsService)ServiceProvider.GetService(typeof(IYbNewProjectsService));
fakeYbService.InjectedResponse = @"[{{""idProjet"":1883557,""dateDApplication"":...
var response = await Client.GetAsync("/api/yb-new-projects");
...I get my faked service. ...我得到了我的伪造服务。 Trouble is, when I call
Client.GetAsync()
, the TestServer is using a clean instance of the same faked service, without my InjectedResponse
.问题是,当我调用
Client.GetAsync()
时,TestServer 正在使用同一伪造服务的干净实例,而没有我的InjectedResponse
。 This is meant to be a singleton, so why are there two of them?这应该是一个 singleton,那么为什么有两个呢?
You don't need to setup a ServiceProvider
yourself, it's available on the Factory
:您不需要自己设置
ServiceProvider
,它在Factory
上可用:
// Use this:
Factory.Services.GetService(typeof(IYbNewProjectsService));
// Instead of:
ServiceProvider.GetService(typeof(IYbNewProjectsService));
It works correctly for me with this setup (.NET 5 Razor pages app + .NET 5 XUnit test project):使用此设置(.NET 5 Razor 页应用程序 + .NET 5 XUnit 测试项目),它对我来说工作正常:
// In app Startup.ConfigureServices:
services.AddSingleton<ITestService, TestService>();
// Test
[Fact]
public async Task Test1()
{
var factory = new WebApplicationFactory<Startup>()
.WithWebHostBuilder(builder =>
{
builder.ConfigureTestServices(services =>
{
services.AddSingleton<ITestService, FakeTestService>();
});
});
var svc = factory.Services.GetService<ITestService>();
svc.Do();
var client = factory.CreateDefaultClient();
await client.GetAsync("http://localhost");
}
The endpoint it calls also gets the ITestService
and calls the method.它调用的端点也获取
ITestService
并调用该方法。 In both cases I hit the breakpoint in the FakeTestService
.在这两种情况下,我都在
FakeTestService
中遇到了断点。
One thing you could check is that does the Startup.ConfigureServices
run before the ConfigureTestServices
?您可以检查的一件事是
Startup.ConfigureServices
是否在ConfigureTestServices
之前运行? In my case it does which allows us to overwrite the service.在我的例子中,它允许我们覆盖服务。 If they were to run in the other order, your test service would get overwritten.
如果它们以其他顺序运行,您的测试服务将被覆盖。 In this case you would need to use
TryAddSingleton
instead in your Startup class.在这种情况下,您需要在 Startup class 中使用
TryAddSingleton
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.