2

框架&包集成测试与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(); 
    } 

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

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

它失败,因为AutoMapper还没有被初始化。 我明白这个问题的方法是,由于TestServerUseStartup方法,它应该使用的API Startup.cs类配置的所有服务(该UseContentRoot指向我的API项目的根)

这显然是没有发生。有人可以告诉我如何配置TestServer,以便AutoMapper配置正确拾取吗?

+0

显示启动类 – Nkosi

+0

更加清晰干净? – bigyanshr

回答

1

应指定在ConfigureServices方法组装: var assembly = typeof(Program).GetTypeInfo().Assembly; services.AddAutoMapper(assembly); 我使用Automapper模块,所以映射配置由AutoMapper自动拾取,但即使是这样,你仍然需要上述的配置。

1

或使用此行

services.AddAutoMapper(typeof(Startup)); 

代替

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

你找到这个问题的任何解决方案,它是在我看来