Почему эти средства сопоставления аргументов NSubstitute не совпадают?C#

Место общения программистов C#
Ответить
Anonymous
 Почему эти средства сопоставления аргументов NSubstitute не совпадают?

Сообщение Anonymous »

Я самостоятельно написал очень простую реализацию MediatR; понять проблему, которую он решает. (Я взял на себя смелость немного изменить имя, поскольку MediatR на самом деле не реализует исходный шаблон GoF Mediator. Пожалуйста, не обращайте на это внимания.)
Я реализовал метод расширения для 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
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»