Asp.net Core 2.1 модульный тест автомата? - PullRequest
0 голосов
/ 06 июня 2018

Сообщение об ошибке

Сообщение: System.InvalidOperationException: Mapper не инициализирован.Вызовите Initialize с соответствующей конфигурацией.Если вы пытаетесь использовать экземпляры mapper через контейнер или иным образом, убедитесь, что у вас нет вызовов статических методов Mapper.Map, и если вы используете методы расширения ProjectTo или UseAsDataSource, убедитесь, что вы передаете соответствующий IConfigurationProvider.instance.

Проект приложения

Определить профиль сопоставления ( ApplicationMappingProfile.cs )

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

Зарегистрировать службы Autopper ()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;
    }
}

Проект модульного тестирования

Создание тестового сервера для запуска 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();
    }
}

И тест ( 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);
    }
}

Этот тестовый метод вызывает метод /api/test/GetUsers/, который использует appservice (PermissionAppService.cs).Эта служба приложения возвращает dto, который сопоставлен с сущностью с использованием automapper.Так что здесь происходит исключение.

Когда я удалил следующую строку:

ServiceCollectionExtensions.UseStaticRegistration = false;

Тогда я получаю следующую ошибку:

Сообщение: System.InvalidOperationException: Mapperуже инициализирован.Вы должны вызывать Initialize один раз для домена / процесса приложения.

Эта ошибка происходит, поскольку существует несколько классов, унаследованных от класса ApiTestBase.Если я запускаю только метод TestAuthorizedAccessAsync, он запускается без проблем.

Вопрос может быть немного сложным, извините за это :), не стесняйтесь спрашивать, где вы не понимаете.

ИСТОЧНИК ПРОЕКТА

Редактировать

Работает, когда я запускаю проект веб-API, который использует appServices

Редактировать2

если я добавлю следующие строки в конструктор TestBase, только один тест не пройден, а другие пройдены.

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

....

enter image description here

Ответы [ 2 ]

0 голосов
/ 22 июня 2018
  • Отключить статическую регистрацию автоматического средства и инициализировать ее для передачи в качестве параметра службе приложения

TestBase.cs

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();
    }
...
  • Передайте mapper как параметр в службу приложения

UserApplicationServiceTests.cs

public class UserApplicationServiceTests : ApplicationTestBase
{
    private readonly IUserAppService _userAppService;

    public UserApplicationServiceTests()
    {
        var userRepository = new Repository<User>(KodkodInMemoryContext);
        _userAppService = new UserAppService(userRepository, Mapper);
    }
...
0 голосов
/ 06 июня 2018

Чтобы избежать этой ошибки:

Сообщение: System.InvalidOperationException: Mapper уже инициализирован.Вы должны вызвать Инициализировать один раз для домена / процесса приложения.

Вам необходимо позвонить Mapper.Reset() перед выполнением каждого теста:

Статический сопоставитель.Initialize предназначен для вызова только один раз.Для сброса конфигурации статического сопоставления

Сброс не должен использоваться в рабочем коде.Он предназначен только для поддержки сценариев тестирования.

Вы можете вызвать его в начале модульного теста, но я рекомендую сделать это в стандартном классе вашего модульного теста, как показано ниже:

public AccountTests()
{
    Mapper.Reset();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...