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); 

你找到這個問題的任何解決方案,它是在我看來