Как выполнить тесты интеграции с Mediatr в .NET framework 4.7?

Я использую библиотеку Mediatr для регистрации и вызова своих RequestHandlers. Все шло нормально, пока я не начал читать больше об интегрированных тестах.

ПОЖАЛУЙСТА, КРАСНЫЙ ПОСЛЕ РЕДАКТИРОВАНИЯ

Я не могу вызвать свой класс, унаследованный от RequesHandler.

Мой класс выглядит так:

public class MyRequestHandler : RequestHandler<MyRequest, MyResponse>
{
  ....
}

Я не использую Meditr async, а использую .net framework 4.7 вместо ядра asp.net, поэтому все, что я выгляжу, возвращает мне ответы для ядра asp.net.

Когда я конструирую MyTestClass, чтобы построить RequestHandler, мне нужно создать ServiceFactory, и, возможно, это проблема, потому что я не знаю, как это сделать.

 public MyClassTest()
 {
    ServiceFactory sv = null;
    _mediator = new Mediator(sv);
 }

ИЗМЕНИТЬ

Предоставление дополнительной информации

У меня есть этот обработчик на уровне приложения

public class LogInUserByFormHandler : RequestHandler<LogInUserByFormRequest, LogInUserByFormResponse>
{
    private readonly IValidator<LogInUserByFormRequest> _validator;

    public LogInUserByFormHandler(IValidator<LogInUserByFormRequest> validator)
    {
        _validator = validator;
    }

    protected override LogInUserByFormResponse Handle(LogInUserByFormRequest request)
    {
        _validator.ValidateAndThrow(request);

        var userInfo = GetUserInfo(request);
        ValidateLogInUserByFormRules(userInfo);

        var userLoginInfo = GetValidUserLoginInfo(request);
        ValidateUserLoginInfoByFormRules(userLoginInfo);

        var sessionKey = CreateUserSessionKey(userInfo);

        var response = new LogInUserByFormResponse
        {
            UserName = request.UserName,
            SessionKey = sessionKey,
            UserId = userInfo.id_usuario
        };
        return response;
    }

    //A LOT OF CODE HERE, methods and etc
}

Как можно видеть, он реализует Mediatr. В моем веб-проекте на уровне презентации я использовал AutoFac для внедрения обработчиков, поэтому любой запрос, который я делаю, всегда обрабатывается правильным методом. Все, что мне нужно сделать, это позвонить, вот так:

var logInByFormRequest = new LogInUserByFormRequest
{
    UserName = viewModel.UserName,
    Password = viewModel.Password
};

var response = _mediator.Send(logInByFormRequest).Result;

Это работает как шарм. Теперь проблема находится в тестовом проекте. Он ссылается на приложение так же, как и проект презентации. Я не знаю, как заставить mediator.send найти правильный метод.

РЕДАКТИРОВАТЬ²

Вот мой тестовый код

[TestClass]
public class LogInUserByFormTest 
{
    private LogInUserByFormRequest CreateRequest(string userName, string password)
    {
        LogInUserByFormRequest request = new LogInUserByFormRequest
        {
            UserName = userName,
            Password = password
        };

        return request;
    }

    [TestMethod]
    [Description("")]
    public void UserName_ShouldHave_Max_30Characters_Exception()
    {
        try
        {
            var request = CreateRequest("UserNameIsGreaterThanAllowed", "password");
            var mediator = new Mock<IMediator>();
            var response = mediator.Object.Send(request).Result;
        }
        catch (System.Exception ex)
        {

            throw;
        }
    }
}

Результат (ответ) всегда равен нулю, и посредник не вызывает правого обработчика.

РЕДАКТИРОВАТЬ3

Вот как я регистрирую обработчики и валидаторы. Пользуюсь автофаком. Этот класс здесь вызывается в global.asax

 public class AutofacConfig
{
    public static void ConfigureContainer()
    {
        var builder = new ContainerBuilder();

        builder.RegisterControllers(Assembly.GetExecutingAssembly()).InstancePerRequest();
        builder.RegisterType<Mediator>().As<IMediator>().InstancePerLifetimeScope();
        builder.RegisterType<AutofacValidatorFactory>().As<IValidatorFactory>().SingleInstance();
        builder.RegisterType<FluentValidationModelValidatorProvider>().As<ModelValidatorProvider>();
        builder.RegisterType<RegistryManagerService>().As<IRegistryManagerService>().SingleInstance().WithParameter("appName", ConfigurationManager.AppSettings["APPNAME"]);

        builder.Register<ServiceFactory>(context =>
        {
            var c = context.Resolve<IComponentContext>();
            return t => c.Resolve(t);
        });

        builder.RegisterAssemblyTypes(Assembly.Load("Docspider.Application"))
            .Where(x => x.Name.EndsWith("Handler"))
            .AsImplementedInterfaces();

        builder.RegisterAssemblyTypes(Assembly.Load("Docspider.Application"))
           .Where(x => x.Name.EndsWith("Validator"))
           .AsImplementedInterfaces()
           .InstancePerLifetimeScope();

        var container = builder.Build();
        DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
    }
}

public class AutofacValidatorFactory : ValidatorFactoryBase
{
    private readonly IComponentContext _context;

    public AutofacValidatorFactory(IComponentContext context)
    {
        _context = context;
    }

    public override IValidator CreateInstance(Type validatorType)
    {
        if (_context.TryResolve(validatorType, out object instance))
        {
            var validator = instance as IValidator;
            return validator;
        }

        return null;
    }
}

person Leandro De Mello Fagundes    schedule 10.08.2019    source источник
comment
Проверьте их репо на пример github.com/jbogard/ MediatR / blob / master / test / MediatR.Tests /   -  person Nkosi    schedule 10.08.2019


Ответы (1)


Для такого интеграционного теста вам нужно будет настроить необходимые зависимости. Поскольку вы указали, что используется Autofac, настройте контейнер так же, как в производственной среде. Используйте контейнер, чтобы получить посредник и выполнить желаемый тест.

Например.

[TestClass]
public class LogInUserByForm_IntegrartionTest {
    private LogInUserByFormRequest CreateRequest(string userName, string password) {
        LogInUserByFormRequest request = new LogInUserByFormRequest {
            UserName = userName,
            Password = password
        };

        return request;
    }

    IMediator BuildMediator() {
        //AutoFac
        var builder = new ContainerBuilder();
        builder.RegisterAssemblyTypes(typeof(IMediator).GetTypeInfo().Assembly).AsImplementedInterfaces();

        var mediatrOpenTypes = new[] {
            typeof(IRequestHandler<,>)
        };

        foreach (var mediatrOpenType in mediatrOpenTypes) {
            builder
                .RegisterAssemblyTypes(typeof(LogInUserByFormRequest).GetTypeInfo().Assembly)
                .AsClosedTypesOf(mediatrOpenType)
                .AsImplementedInterfaces();
        }

        builder.Register<ServiceFactory>(ctx => {
            var c = ctx.Resolve<IComponentContext>();
            return t => c.Resolve(t);
        });

        //...all other needed dependencies.

        //...

        var container = builder.Build();

        var mediator = container.Resolve<IMediator>();
        return mediator;
    }

    [TestMethod]
    [Description("")]
    public async Task UserName_ShouldHave_Max_30Characters_Exception() {
        try
        {
            //Arrange
            var request = CreateRequest("UserNameIsGreaterThanAllowed", "password");
            var mediator = BuildMediator();

            //Act
            var response = await mediator.Send(request);

            //Assert
            //...assert the expected values of response.
        }
        catch (System.Exception ex)
        {

            throw;
        }
    }
}

Вышеупомянутое было смоделировано на основе примеров, предоставленных MediatR .Examples.Autofac

person Nkosi    schedule 10.08.2019
comment
@LeandroDeMelloFagundes рад помочь. Удачного кодирования. - person Nkosi; 10.08.2019