В моем тесте строка подключения пуста после первого обращения к базе данных.Зачем? - PullRequest
0 голосов
/ 12 октября 2018

Я использую XUnit, FakeItEasy и Dapper.Я тестирую вызов .NET Core 2.1 WebAPI.Когда я раскручиваю реальный веб-сайт, у меня нет ошибок.Что-то не так с моим тестом.

Для XUnit я использую DatabaseFixture примерно так:

public class DatabaseFixture : IDisposable
{
    public DatabaseFixture()
    {
        Settings = GetSettings();
        var serviceProvider = CreateServices();

        using (var scope = serviceProvider.CreateScope())
        {
            EnsureDatabase();
            UpdateDatabase(scope.ServiceProvider);
            Db = new SqlConnection(Settings.TestDbConnectionString);
        }
    }
    ...

Мой веб-контроллер выглядит так:

    public async Task<ActionResult> Authorization()
    {
        ...
        var user = await _userRepository.FindBySubject(subject);  // <== First call to DB, all good
        if (user == null) return Ok(new { UserNotRegistered = true });

        var roles = await _userRepository.GetRoles(subject); // <== Second call to DB, ConnectionString off of Fake is ""
        ....

        return Ok(roles);
    }

UserRepo выглядит следующим образом:

public class UserRepository 
{
    ....
    public async Task<Membership> FindByNameAsync(string subject_cn, CancellationToken cancellationToken)
    {
        using (var connection = _connectionFactory.GetConnection())
        {
            return await connection.QuerySingleOrDefaultAsync<Membership>($@"SQL Code", new {subject_cn});
        }
    }

    public async Task<Membership> FindBySubject(string subject_cn)
    {
        return await FindByNameAsync(subject_cn, new CancellationToken());  // First call, all good
    }

    public async Task<IList<string>> GetRoles(string subject_cn)
    {
        var membership = await FindBySubject(subject_cn); //Second call, no connection string :(
        return await GetRolesAsync(membership, new CancellationToken());
    }

И, наконец, и, возможно, самый важный мой тест:

[Collection(nameof(DatabaseFixture))]
public class UserControllerTests
{
    private readonly IDatabaseConnectionFactory _connectionFactory;
    public UserControllerTests(DatabaseFixture fixture)
    {
        _connectionFactory = A.Fake<IDatabaseConnectionFactory>();
        A.CallTo(() => _connectionFactory.GetConnection()).Returns(fixture.Db);
    }

    [Fact]
    public async Task Authorize_ReturnsRoles()
    {
        var configurationManager = A.Fake<IConfigurationManager>();
        A.CallTo(() => configurationManager.GetSettings()).Returns(new Web.Settings() { ... stuff ... });

        var authenticationManager = A.Fake<IAuthenticationManager>();

        var userController = new UserController(new UserRepository(_connectionFactory), authenticationManager, configurationManager);

        var response = await userController.Authorization(); // Connection string is empty on second data call
        var viewResult = Assert.IsType<ViewResult>(response);
        var model = Assert.IsAssignableFrom<AuthorizationResult>(viewResult);

        Assert.Contains("A Role", model.Roles);
        Assert.Equal(AuthorizationResult.UserState.Authenticated, model.Status);
        A.CallTo(() => authenticationManager.AddToRoles(A.Fake<Membership>(), model.Roles)).MustHaveHappened();
        A.CallTo(() => authenticationManager.SignIn(A.Fake<Membership>())).MustHaveHappened();
    }
}

Я не уверен, как фальшивка "забывает" строку подключения.Конкретная возвращаемая ошибка: Message: System.InvalidOperationException : The ConnectionString property has not been initialized. Когда я отлаживаю после первого вызова, убедитесь, что строка подключения на объекте подключения пуста.Кто-нибудь может пролить свет на эту ситуацию?

1 Ответ

0 голосов
/ 16 октября 2018

Я не уверен, что именно происходит.Я не думаю, что проблема с FakeItEasy, так как само соединение не является подделкой.В качестве обходного пути вы можете заставить фабрику фальшивых соединений возвращать новое соединение для каждого вызова:

A.CallTo(() => _connectionFactory.GetConnection())
    .ReturnsLazily(() => new SqlConnection(settings.TestDbConnectionString)).
...