Singleton Constructor 에 Scoped 서비스가 있다면?

정상적인 상황이라면 Singleton 에서는 Scoped lifetime을 가진 서비스를 생성할 수 없을테고, 이런때에는 아래와 같은 메세지가 발생합니다.

InvalidOperationException: Cannot resolve scoped service 'xxx' from root provider.

하지만 어떤때에는 이렇게 에러가 발생해서 유닛테스트나 기타 테스트에서 바로 잡히지만

어떤때에는 아무런 문제없이 코드가 돌아가서 유닛테스트를 통과했지만 실제로 서비스를 띄울 때에 exception이 발생하기도 합니다.

아래는 같은 상황에 대한 예제코드인데요,
A = Scoped,
B = Singleton 상태입니다.

아래 코드를 실행해보면 저는 문제없이 동작합니다.

저는 Scoped 로 inject 된 서비스를 singleton에서 호출하려고 할 때 일관되게 exception이 발생하길 바랍니다. 혹시 관련된 내용에 대해 아는분 계신가요?

using Microsoft.Extensions.DependencyInjection;

ServiceCollection services = new ServiceCollection();

services.AddScoped<A>();
services.AddSingleton<B>();

var provider = services.BuildServiceProvider();

var bb1 = provider.CreateScope().ServiceProvider.GetRequiredService<B>();
var bb2 = provider.GetRequiredService<B>();

public class A // Scoped
{

}

public class B // Singleton
{
    public B(A a)
    {
        A = a;
    }

    public A A { get; }
}
좋아요 1

이미 알고 계시는대로…

제가 봤을때 올려주신 샘플 코드가 제대로 되어있어서, 해당 코드 처럼 적용이 되었다면 어떠한곳에서도 다르게 동작하지 않아야하는거 같습니다.

단위 테스트에서만 예상대로 동작하지 않는다면 단위 테스트에서의 환경 구성이 실제 환경과 차이가 있다는건데… 그러한 부분을 살펴 보셨을까요?

( 여기서 제가 말하는 환경 구성은 ServiceCoellection 구성과 같은 종속성들의 구성 입니다.)

좋아요 1

일단 테스트 해보았을 때 IServiceProvider 만 가지고는 Singleton에서 Scoped lifetime을 가진 서비스를 호출하여도 문제가 발생하지 않는것으로 확인하였습니다.

저는 주로 api서버를 많이 만드는데, 이때 IWebHostBuilder 등을 통해서 어플리케이션 설정하고, 관련된 설정을 비슷하게 Microsoft.AspNetCore.TestHost 유닛테스트에서 실행하는데, 유닛테스트에서는 문제가 없지만 서버를 띄우면 에러가 나는것으로 보입니다.

hostbuilder에서 아래처럼 validation 관련된 값을 넣어주면 런타임 기본설정값과 상관없이 builder.Build() 할 때 di 구성이 잘못되었다면 서버가 켜지는 즉시 확인이 가능합니다.

다만, Console Application 처럼 ServiceCollection을 직접 사용할 때에는 여전히 어떻게 해야할지 알 수가 없었습니다.

.UseDefaultServiceProvider((context, options) =>
{
   options.ValidateScopes = true;
   options.ValidateOnBuild = true;
})
좋아요 1