Предыстория: я пишу тесты вокруг сервисов, использующих ядро ef.Я хочу использовать sqllite, поскольку он является реляционным.
Я написал базовый класс для тестов, которые будут использовать фабрику mock db, которую я написал, для настройки базовых базовых вещей, таких как http-mocking и DAL.
namespace Bll.UnitTests
{
public class TestBase : IDisposable
{
// pass httpclient as dependency, setup messageHandler for stubbing
protected HttpClient httpClient;
protected Mock<HttpMessageHandlerFake> fakeHttpMessageHandler = new Mock<HttpMessageHandlerFake> { CallBase = true };
protected Mock<Logger> loggerMock;
protected DalContext dataContext;
protected MockDbFactory mockDbFactory;
public TestBase()
{
mockDbFactory = new MockDbFactory();
httpClient = new HttpClient(fakeHttpMessageHandler.Object);
dataContext = mockDbFactory.testDb;
loggerMock = new Mock<Logger>(dataContext);
}
public void Dispose()
{
mockDbFactory.Dispose();
}
}
}
Вот моя фабрика фиктивных БД, которая должна просто установить соединение в памяти и, кажется, работает.
using Dal;
using Microsoft.EntityFrameworkCore;
using Moq;
using Microsoft.Data.Sqlite;
using System;
using System.Collections.Generic;
namespace Bll.UnitTests.Factories
{
// In-memory database only exists while the connection is open
public class MockDbFactory : IDisposable
{
private SqliteConnection connection;
public DalContext testDb;
public MockDbFactory()
{
OpenConnection();
testDb = GetTestDb();
}
public void Dispose()
{
CloseConnection();
}
private void OpenConnection()
{
connection = new SqliteConnection("DataSource=:memory:");
connection.Open();
}
private void CloseConnection()
{
connection.Close();
}
private DalContext GetTestDb()
{
var options = new DbContextOptionsBuilder<DalContext>()
.UseSqlite(connection)
.Options;
// Create the schema in the database
using (var context = new DalContext(options))
{
context.Database.EnsureCreated();
return context;
}
}
}
}
В моем тестовом классе datacontext удаляется, когда я отлаживаю тестируемый сервис.
public class LocationServiceTest : TestBase
{
private LocationService sut;
public LocationServiceTest(): base()
{
sut = new LocationService(
httpClient,
loggerMock.Object,
dataContext
);
}
[Fact]
public async Task UpdateCountriesAsync_CallsCountryApiAndUpdatesDatabase()
{
// arrange
// setup get country data to return 2 countries
var temp = BuildCountryApiReturnable(2);
fakeHttpMessageHandler.Setup(f => f.Send(It.IsAny<HttpRequestMessage>())).Returns(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent(temp)
});
// act
try
{
var result = await sut.UpdateCountriesAsync();
// assert
Assert.True(dataContext.Country.Count() == 2);
Assert.True(dataContext.Location.Count() == 2);
}
catch(Exception e)
{
throw e;
}
}
Я думаю, что понимаю, что необходимо использование оператора using, поскольку это создаст мое соединение и избавится от него, но я пытаюсь сделать это вручную, чтобы я мог внедрить контекст данных в свой сервис.Если мне придется все обернуть в оператор использования, я буду вынужден изменить свой сервис ..