如何在 .net framework 4.7 上使用 Mediatr 进行集成测试?

Posted

技术标签:

【中文标题】如何在 .net framework 4.7 上使用 Mediatr 进行集成测试?【英文标题】:How to do Integration Tests with Mediatr on .net framework 4.7? 【发布时间】:2019-12-17 23:10:28 【问题描述】:

我正在使用 Mediatr 库来注册和调用我的 RequestHandlers。 一切都很顺利,直到我开始阅读有关集成测试的更多信息。

请在编辑后阅读

我无法调用继承自 RequesHandler 的类。

我的班级是这样的:

public class MyRequestHandler : RequestHandler<MyRequest, MyResponse>

  ....

我没有使用 Meditr async,我使用的是 .net 框架 4.7 而不是 asp.net 核心,所以,一切看起来都像是为我返回了 asp.net 核心的答案。 p>

当我构造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。 在表示层的 Web 项目中,我使用 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;
        
    

结果(响应)始终为 null,并且中介者没有调用正确的处理程序。

EDIT3

这是我注册处理程序和验证程序的方式。 我使用自动法。这里的这个类是在 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;
    

【问题讨论】:

查看他们的仓库以获取示例github.com/jbogard/MediatR/blob/master/test/MediatR.Tests/… 【参考方案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提供的例子

【讨论】:

@LeandroDeMelloFagundes 很高兴为您提供帮助。编码愉快。

以上是关于如何在 .net framework 4.7 上使用 Mediatr 进行集成测试?的主要内容,如果未能解决你的问题,请参考以下文章

是否可以在 .net framework 4.7 中使用 AES(256 位)GCM 模式加密数据?

. net framework 4.7安装未成功,提示已处理证书链,但是在不受信任程序信任的根证书?

在 Azure Web App(.NET Framework 4.7)上发布后,“SpeechSynthesizer”不起作用

.Net Core 3.x 与 .Net Framework 4.7 的兼容性

在 Windows Server 2016 上的 Visual Studio 安装程序中找不到 .NET Framework 4.7 目标包

windows server 2019如何卸载net framework?