Я реализовал метод расширения для IServiceCollection, который сканирует сборки и вызывает вызовы IServiceCollection. .AddTransient(IRequestHandler, SomeRequestTypeHandler); для всех реализаций IRequestHandler.
При тестировании вручную он работает как шарм. Однако при добавлении следующего автоматического теста, подтверждающего, что AddTransient() вызывается для IRequestHandler и VoidDispatcherRequestHandler, тест не пройдет. Почему?
Код: Выделить всё
[Fact]
public void When__Given__Then()
{
// Arrange
var serviceCollection = Substitute.For();
// Act
RequestDispatcherRegistrar.AddRequestDispatcher(serviceCollection);
// Assert
serviceCollection.Received()
.AddTransient(Arg.Is(t => t == typeof(IRequestHandler)),
Arg.Is(t => t == typeof(VoidDispatcherRequestHandler)));
}
Код: Выделить всё
System.ArgumentNullException: Value cannot be null. (Parameter 'serviceType')
System.ArgumentNullException
Value cannot be null. (Parameter 'serviceType')
at System.ThrowHelper.Throw(String paramName)
at Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddTransient(IServiceCollection services, Type serviceType, Type implementationType)
at Presentation.Functional.UnitTest1.When__Given__Then() in [...]
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr).
Код: Выделить всё
public interface IRequest : IBaseRequest { }
public interface IBaseRequest { }
public class VoidDispatcherRequest : IRequest { }
public interface IRequestHandler
where TRequest : IRequest
{
Task HandleAsync(TRequest request, CancellationToken cancellationToken);
}
public class VoidDispatcherRequestHandler : IRequestHandler
{
public Task HandleAsync(VoidDispatcherRequest request, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
}
Код: Выделить всё
[Fact]
public void When__Given__Then()
{
// Arrange
var serviceCollection = Substitute.For();
// Act
RequestDispatcherRegistrar.AddRequestDispatcher(serviceCollection);
// Assert
serviceCollection.Received()
.AddTransient(typeof(IRequestHandler), typeof(VoidDispatcherRequestHandler));
}
Код: Выделить всё
NSubstitute.Exceptions.ReceivedCallsException: Expected to receive a call matching:
NSubstitute.Exceptions.ReceivedCallsException
Expected to receive a call matching:
Add(ServiceType: Application.IRequestHandler`1[Presentation.Functional.VoidDispatcherRequest] Lifetime: Transient ImplementationType: Presentation.Functional.VoidDispatcherRequestHandler)
Actually received no matching calls.
Received 5 non-matching calls (non-matching arguments indicated with '*' characters):
Add(*ServiceType: Application.IRequestHandler`2[Presentation.Functional.DispatcherRequest,Presentation.Functional.DispatcherResponse] Lifetime: Transient ImplementationType: Presentation.Functional.DispatcherRequestHandler*)
[...]
**Add(*ServiceType: Application.IRequestHandler`1[Presentation.Functional.VoidDispatcherRequest] Lifetime: Transient ImplementationType: Presentation.Functional.VoidDispatcherRequestHandler*)**
[...]
Add(*ServiceType: Application.IRequestDispatcher Lifetime: Transient ImplementationFactory: Application.IRequestDispatcher b__0_0(System.IServiceProvider)*)
at NSubstitute.Core.ReceivedCallsExceptionThrower.Throw(ICallSpecification callSpecification, IEnumerable`1 matchingCalls, IEnumerable`1 nonMatchingCalls, Quantity requiredQuantity)
at NSubstitute.Routing.Handlers.CheckReceivedCallsHandler.Handle(ICall call)
at NSubstitute.Routing.Route.Handle(ICall call)
at NSubstitute.Core.CallRouter.Route(ICall call)
at NSubstitute.Proxies.CastleDynamicProxy.CastleForwardingInterceptor.Intercept(IInvocation invocation)
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at NSubstitute.Proxies.CastleDynamicProxy.ProxyIdInterceptor.Intercept(IInvocation invocation)
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Castle.Proxies.ObjectProxy.Add(ServiceDescriptor item)
at Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddTransient(IServiceCollection services, Type serviceType, Type implementationType)
at Presentation.Functional.UnitTest1.When__Given__Then() in [...]
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
Я знаю, что имена проектов на данный момент не оптимальны. Пожалуйста, не обращайте на это внимания.
Подробнее здесь: https://stackoverflow.com/questions/788 ... t-matching
Мобильная версия