Как мне настроить интеграционные тесты для использования тестовой базы данных с Entity Framework?
Я пишу интеграционные тесты для приложения и не смог найти каких-либо рекомендаций по настройке тестовой базы данных для моего пакета интеграции. Я работаю над приложением ASP.NET MVC4, используя сначала код Entity Framework.
Я могу подтвердить, что тесты в моем тестовом проекте по умолчанию сообщаются с локальной базой данных разработки на моем компьютере. Это не идеально, поскольку я хочу иметь новую базу данных каждый раз, когда я запускаю тесты.
Как настроить тестовый проект, чтобы мои тесты говорили об отдельном экземпляре? Я предполагаю, что можно создать экземпляр SQL Server Compact Edition, но я не уверен, как его настроить.
Ответы
Ответ 1
Большое спасибо @Justin и @Petro за ваши ответы, которые очень помогли мне. Решение, которое я придумал, представляет собой комбинацию методов, которые вы предложили. Решение, описанное ниже, предоставляет новую базу данных для каждого запуска тестов и отдельную транзакцию для каждого теста.
Я добавил строку подключения для моей тестовой базы данных в App.config моего тестового проекта:
<connectionStrings>
<add name ="TestDatabase"
providerName="System.Data.SqlClient"
connectionString="Data Source=(LocalDb)\v11.0;Database=TestDatabase;Integrated Security=True"/>
</connectionStrings>
Я создал базовый класс для своих интеграционных тестов, чтобы обеспечить настройку и отключение. Программа установки создает экземпляр контекста, создает БД, если он еще не существует, и начинает транзакцию. Teardown отменяет транзакцию.
public class EntityFrameworkIntegrationTest
{
protected MyDbContext DbContext;
protected TransactionScope TransactionScope;
[TestInitialize]
public void TestSetup()
{
DbContext = new MyDbContext(TestInit.TestDatabaseName);
DbContext.Database.CreateIfNotExists();
TransactionScope = new TransactionScope(TransactionScopeOption.RequiresNew);
}
[TestCleanup]
public void TestCleanup()
{
TransactionScope.Dispose();
}
}
Наконец, у меня есть класс, который заботится об удалении базы данных после выполнения всех тестов:
[TestClass]
public static class TestInit
{
// Maps to connection string in App.config
public const string TestDatabaseName = "TestDatabase";
[AssemblyCleanup]
public static void AssemblyCleanup()
{
Database.Delete(TestDatabaseName);
}
}
Я должен добавить, что нашел это сообщение в блоге о Entity Framework, полезное для более глубокого понимания того, что Entity Framework делает под капотом /by условность.
Ответ 2
Просто настройте строку подключения в app.config вашего проекта unit test, который указывает на новый экземпляр DB.
Затем вы можете использовать методы инициализации и очистки в вашем тестовом классе для создания и удаления БД.
Строка подключения является обычной, например.
<add name="UnitTestDBConnection" connectionString="Data Source=(local);Initial Catalog=UnitTestDB;Integrated Security=SSPI;" providerName="System.Data.SqlClient"/>
Затем, чтобы создать БД, один раз за тест, вы могли бы сделать:
YourContext _ctx;
[TestInitialize]
public void Initiaslise()
{
YourNameDbInitialise initialiser = new YourNameDbInitialiseForTest();
Database.SetInitializer(initialiser);
_ctx = new YourNameContext();
initialiser.InitializeDatabase(_ctx);
}
и это удалить в конце каждого теста
[TestCleanup]
public void Cleanup()
{
Database.Delete("YourName");
}
Ответ 3
Если вы используете NUnit, вы можете использовать атрибут Setup/Teardown
с TransactionScope
, чтобы не совершать изменения в базе данных:
[SetUp]
public void SetUp()
{
transaction = new TransactionScope();
}
[TearDown]
public void TearDown()
{
if(transaction != null)
transaction.Dispose();
}
Если вы используете какую-либо другую структуру unit test, она должна иметь близкие атрибуты. Я бы рекомендовал создать базовый класс DbItegrationTest
для всех ваших интеграционных тестов, поэтому, если вы выйдете из этого класса, все методы тестирования не будут выполнять привязки к базе данных.
Чтобы настроить Entity Framework для другой базы данных, пожалуйста, переопределите строку соединения db в тестовой сборке.