2

框架和包

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

启动.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方法,它应该使用apiStartup.cs类中配置的所有服务(UseContentRoot指向我的api项目根)

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

4

3 回答 3

1

您应该在 ConfigureServices 方法中指定程序集: var assembly = typeof(Program).GetTypeInfo().Assembly; services.AddAutoMapper(assembly); 我正在使用 Automapper 模块,因此 AutoMapper 会自动获取映射配置,但即便如此,您仍然需要上述配置。

于 2017-09-11T14:47:36.020 回答
1

或者只是使用这条线

 services.AddAutoMapper(typeof(Startup));

代替

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

我认为哪个更清晰干净

于 2017-11-12T07:35:35.223 回答
0

谢谢,这对我有用。此外,您可以添加这样的配置选项。

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

        services.AddAutoMapper(cfg =>
        {
            cfg.AllowNullDestinationValues = true;
            cfg.CreateMap<ApplicationUser, ApplicationUserView> ().IgnoreAllPropertiesWithAnInaccessibleSetter();}, assembly);
于 2018-11-09T07:30:09.303 回答