im writing integration tests but im currently stuck … one of scoped services require extra initialization step to set private field but when i try to call this extra step in test code it is not working as expected:
imagine this 3rd party service (this code i cannot change):
interface IScopedService {
bool IsFooValid(int foo);
}
class ScopedService {
private List<int> _Foo = new();
public void Register(int foo){
_Foo.Add(foo);
}
public bool IsFooValid(int foo){
return _Foo.Contains(foo);
}
}
that is used by my controller:
class MyController(IScopedService scopedServiceInController) : ApiController {
[HttpPost]
public bool MyFunc(int foo){
return scopedServiceInController.IsFooValid(foo);
}
}
which is called from client via:
class MyEndpoints(HttpClient httpClient) {
public bool MyFunc(int foo){
var request = new HttpRequestMessage(HttpMethod.Post, $"path") {
Content = JsonContent.Create(foo)
};
var result = await httpClient.SendAsync(request);
if (!result.IsSuccessStatusCode) {
return null;
}
return await result.Content.ReadFromJson<bool>();
}
}
and integration test for that:
class MyWebApplicationFactory: WebApplicationFactory<Program>, IAsyncLifetime {
public IServiceProvider ScopedServiceProvider => _Scope.ServiceProvider;
private IServiceScope _Scope;
public virtual async Task InitializeAsync() {
_Scope = Services.CreateScope();
}
public new virtual async Task DisposeAsync() {
_Scope.Dispose();
}
}
class MyServiceTests: IClassFixture<MyWebApplicationFactory> {
private readonly MyWebApplicationFactory _Factory;
private readonly MyEndpoints _Sut;
public MyServiceTests(MyWebApplicationFactory factory){
_Factory = factory;
var client = factory.CreateClient();
_Sut = new MyEndpoints(client);
}
[Fact]
public void Test(){
// Arrange
var scopedServiceInTest = _Factory.ScopedServiceProvider.GetRequiredService<ScopedService>();
scopedServiceInTest.Register(1);
// Act
var actual = _Sut.MyFunc(1);
// Assert
actual.Should.BeTrue();
}
}
}
my troube is that scopedServiceInController
is not same instance as scopedServiceInTest
=> foo list is not initialized => test will fail
my theory is that i should not create new scope in MyWebApplicationFactory but get instance of scope that server uses to resolve scopedServiceInController
…
any idea how to fix this?
PS: in my code ScopedService
is Microsoft.AspNetCore.Identity.UserManager<User>
and i need to call RegisterTokenProvider
method if that helps …