与AutoMapper的集成测试无法初始化配置 [英] Integration Testing with AutoMapper fails to initialise configuration

查看:107
本文介绍了与AutoMapper的集成测试无法初始化配置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

框架和软件包

.NETCoreApp 1.1
Xunit 2.2.0
AutoMapper 6.0.2
Microsoft.AspNetCore.TestHost 1.1.1
Microsoft.NET.Test.Sdk 15.0.0

集成测试

public class ControllerRequestsShould
{
    private readonly TestServer _server;
    private readonly HttpClient _client;

    public ControllerRequestsShould()
    {
        _server = new TestServer(new WebHostBuilder()
            .UseContentRoot(Constants.apiProjectRoot)
            .UseStartup<Startup>()
            .UseEnvironment(Constants.testingEnvironment));
        _client = _server.CreateClient();
        _client.BaseAddress = new Uri(Constants.localHostUri);
    }

    [Fact]
    public async Task CreateAnEntity()
    {
        // Arrange
        var entityForCreationDto = new entityForCreationDto { Code = "00001", Name = "Entity One" };
        var jsonContent = JsonConvert.SerializeObject(entityForCreationDto);
        var stringContent = new StringContent(jsonContent);
        stringContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");

        // Act
        var response = await _client.PostAsync("/api/controller", stringContent);
        response.EnsureSuccessStatusCode();

        // Assert
        Assert.Equal(HttpStatusCode.OK, response.StatusCode);
    }
}

Startup.cs

public class Startup
{
    public IConfigurationRoot Configuration { get; }

    public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
            .AddEnvironmentVariables();
        Configuration = builder.Build();
    }

    // This method gets called by the runtime. Use this method to add services to the container.
    // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
    public void ConfigureServices(IServiceCollection services)
    {
        // Add framework services
        services.AddMvc(setupAction =>
        {
            setupAction.ReturnHttpNotAcceptable = true;
            setupAction.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());
            setupAction.InputFormatters.Add(new XmlDataContractSerializerInputFormatter());
        });

        // Db context configuration
        var connectionString = Configuration["ConnectionStrings:DefaultConnection"];
        services.AddDbContext<YourContext>(options =>
        {
            options.UseSqlServer(connectionString);
        });

        // Register services for dependency injection
        services.AddScoped<IYourRepository, YourRepository>();

        services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();

        services.AddScoped<IUrlHelper, UrlHelper>(implementationFactory =>
        {
            var actionContext =
                implementationFactory.GetService<IActionContextAccessor>().ActionContext;
            return new UrlHelper(actionContext);
        });
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        loggerFactory.AddConsole();
        loggerFactory.AddDebug(LogLevel.Information);
        loggerFactory.AddNLog();

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler(appBuilder =>
            {
                appBuilder.Run(async context =>
                {
                    var exceptionHandlerFeature = context.Features.Get<IExceptionHandlerFeature>();
                    if (exceptionHandlerFeature != null)
                    {
                        var logger = loggerFactory.CreateLogger("Global exception logger");
                        logger.LogError(500,
                            exceptionHandlerFeature.Error,
                            exceptionHandlerFeature.Error.Message);
                    }

                    context.Response.StatusCode = 500;
                    await context.Response.WriteAsync("An unexpected fault happened.  Try again later");
                });
            });
        }

        Mapper.Initialize(cfg =>
        {
            cfg.CreateMap<DataStore.Entities.Entity, Models.EntityDto>();
            cfg.CreateMap<Models.EntityDto, DataStore.Entities.Entity>();
            cfg.CreateMap<Models.EntityForCreationDto, DataStore.Entities.Entity>();
            cfg.CreateMap<DataStore.Entities.Entity, Models.EntityForCreationDto>();
        });

        app.UseMvc();
    }

问题
调用控制器方法后,集成测试失败:

Problem
The integration test fails after the controller method is invoked:

var response = await _client.PostAsync("/api/controller", stringContent);

失败,因为尚未初始化AutoMapper. 我的理解是,由于TestServer具有UseStartup方法,因此它应该使用api Startup.cs类中配置的所有服务(UseContentRoot指向我的api项目根目录)

It fails because AutoMapper has not been initialised. The way I understood this was that since the TestServer has the UseStartup method, it should use all the services configured in the api Startup.cs class (the UseContentRoot is pointing to my api project root)

这显然没有发生.有人可以告诉我如何配置TestServer以便正确选择AutoMapper配置吗?

This clearly isn't happening. Could someone show me how I need to configure the TestServer so that the AutoMapper configuration is picked up correctly please?

推荐答案

或仅使用此行

 services.AddAutoMapper(typeof(Startup));

代替

var assembly = typeof(Program).GetTypeInfo().Assembly;
services.AddAutoMapper(assembly);

我认为这更清晰,更干净

which is more clear and clean in my opinion

这篇关于与AutoMapper的集成测试无法初始化配置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆