Asp.net核心2.1单元测试自动播放器?

Ali*_*hşi 5 c# unit-testing automapper asp.net-core

错误信息

消息:System.InvalidOperationException:Mapper未初始化.使用适当的配置调用Initialize.如果您正试图通过容器或以其它方式使用映射器实例,请确保您不必静态Mapper.Map方法的任何电话,如果你使用ProjectTo或UseAsDataSource扩展方法,确保你在适当的IConfigurationProvider通实例.

应用项目

定义映射配置文件(ApplicationMappingProfile.cs)

public class ApplicationMappingProfile : Profile
{
    public ApplicationMappingProfile()
    {
        CreateMap<User, UserListDto>();
        CreateMap<Permission, PermissionListDto>();
        // add auto mapper mapping configurations here
    }
}
Run Code Online (Sandbox Code Playgroud)

注册automapper服务(ApplicationServiceCollectionExtensions.cs)

public static class ApplicationServiceCollectionExtensions
{
    public static IServiceCollection AddKodkodApplication(this IServiceCollection services)
    {
        services.AddAutoMapper();

        //todo: add conventional registrar
        services.AddTransient<IUserAppService, UserAppService>();
        services.AddTransient<IPermissionAppService, PermissionAppService>();

        return services;
    }
}
Run Code Online (Sandbox Code Playgroud)

单元测试项目

创建一个测试服务器以运行Startup.cs(ApiTestBase.cs)

public class ApiTestBase : TestBase
{
    protected static HttpClient Client;

    public ApiTestBase()
    {
        //if this is true, Automapper is throwing exception
        ServiceCollectionExtensions.UseStaticRegistration = false;

        Client = GetTestServer();
    }

    private static HttpClient GetTestServer()
    {
        if (Client != null)
        {
            return Client;
        }

        var server = new TestServer(
            new WebHostBuilder()
                .UseStartup<Startup>()
                .ConfigureAppConfiguration(config =>
                {
                    config.SetBasePath(Path.GetFullPath(@"../../.."));
                    config.AddJsonFile("appsettings.json", false);
                })
        );

        return server.CreateClient();
    }
}
Run Code Online (Sandbox Code Playgroud)

并测试(AccountTests.cs).

public class AccountTests : ApiTestBase
{
    [Fact]
    public async Task TestAuthorizedAccessAsync()
    {
        var responseLogin = await LoginAsTestUserAsync();
        var responseContent = await responseLogin.Content.ReadAsAsync<OkObjectResult>();
        var responseJson = JObject.Parse(responseContent.Value.ToString());
        var token = (string)responseJson["token"];

        var requestMessage = new HttpRequestMessage(HttpMethod.Get, "/api/test/GetUsers/");
        requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
        var responseGetUsers = await Client.SendAsync(requestMessage);
        Assert.Equal(HttpStatusCode.OK, responseGetUsers.StatusCode);

        var users = await responseGetUsers.Content.ReadAsAsync<PagedList<UserListDto>>();
        Assert.True(users.Items.Count > 0);
    }
}
Run Code Online (Sandbox Code Playgroud)

此测试方法调用/api/test/GetUsers/使用appservice(PermissionAppService.cs)的方法.此应用程序服务返回使用automapper从实体映射的dto.所以这里发生了异常.

当我删除以下行时:

ServiceCollectionExtensions.UseStaticRegistration = false;
Run Code Online (Sandbox Code Playgroud)

然后我收到以下错误:

消息:System.InvalidOperationException:Mapper已初始化.您必须为每个应用程序域/进程调用一次Initialize.

发生此错误,因为有多个类从ApiTestBase类继承.如果我只运行TestAuthorizedAccessAsync方法,它运行没有问题.

这个问题可能有点复杂,对不起抱歉:)随便问一下你不明白的地方.

项目来源

编辑

它在我运行使用appServices的web api项目时有效

EDIT2

如果我将以下行添加到TestBase构造函数中,则只有一个测试失败而其他测试通过.

public TestBase()
{
    lock (ThisLock)
    {
        Mapper.Reset();
        Client = GetTestServer();
    }

....
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

Ali*_*hşi 5

  • 禁用自动映射器静态注册并将其初始化为作为参数传递给应用服务

测试库

public class TestBase
{
    private static Dictionary<string, string> _testUserFormData;

    protected readonly IMapper Mapper;
    protected readonly KodkodDbContext KodkodInMemoryContext;
    protected readonly ClaimsPrincipal ContextUser;
    protected readonly HttpClient Client;
    protected async Task<HttpResponseMessage> LoginAsTestUserAsync()
    {
        return await Client.PostAsync("/api/account/login",
            _testUserFormData.ToStringContent(Encoding.UTF8, "application/json"));
    }

    public TestBase()
    {
        // disable automapper static registration
        ServiceCollectionExtensions.UseStaticRegistration = false;

        // Initialize mapper
        Mapper = new Mapper(
            new MapperConfiguration(
                configure => { configure.AddProfile<ApplicationMappingProfile>(); }
            )
        );
        Client = GetTestServer();

        _testUserFormData = new Dictionary<string, string>
        {
            {"email", "testuser@mail.com"},
            {"username", "testuser"},
            {"password", "123qwe"}
        };

        KodkodInMemoryContext = GetInitializedDbContext();
        ContextUser = GetContextUser();
    }
...
Run Code Online (Sandbox Code Playgroud)
  • 将映射器作为参数传递给应用服务

UserApplicationServiceTests.cs

public class UserApplicationServiceTests : ApplicationTestBase
{
    private readonly IUserAppService _userAppService;

    public UserApplicationServiceTests()
    {
        var userRepository = new Repository<User>(KodkodInMemoryContext);
        _userAppService = new UserAppService(userRepository, Mapper);
    }
...
Run Code Online (Sandbox Code Playgroud)