2016-02-29 2 views
0

Как создать единичный тест, который частично использует тесты модулей базы данных, но вызывается из регулярного модульного теста?операции с базами данных в качестве предпосылки для модульных тестов?

Да, возможно, они не могут быть модульными испытаниями; вы можете назвать их интеграционными тестами. Независимо от того, что вы хотели бы назвать их, это тесты.

В моих NUnit тестов, я использую вспомогательные константы:

private const string NumericSerial="123123"; 
private const string NonNumericSerial="123123 bad serialnumber"; 
private const int ValidPatientId=123; 
private const int InvalidPatientId=-1; 
private const int PatientIdThatDoesNotExistInppp=111291; 
private const string SerialNumberThatDoesNotExistInshmk="123123"; 
private const string SerialNumberThatDoesExistInshmk="1015873"; 
private const byte InvalidFirmwareVersion=0; 
private const int FacilityThatDoesntExistInAAA=Int32.MaxValue; 

Перед запуском каких-либо тестов, которые делают использование этих констант, я хотел бы, чтобы убедиться, что эти постоянные корректно определены.

Например, я могу утверждать, что NumericSerial действительно является числовым без необходимости делать какие-либо издевки или инъекции любых зависимостей - я бы просто tryparse.

Однако другие константы, такие как PatientIdThatDoesNotExistInppp необходимо будет проверить, что это действительно не существует в базе данных ррр. Для того, чтобы сделать это, я могу следовать нескольким маршрутам:

  1. Реализовать Linq запрос в рамках общей структуры объекта
  2. Явным отправить отборное заявление в базу данных
  3. Или я мог бы тест блока базы данных, первым создавая необходимо запись (в нашем случае это будет убедиться, что 111291 не существует в базе данных.

Если вы не сильно советуют вариант № 3, я склонен реализовать это. Как создать модульный тест, который частично использует базу данных но вызывается из регулярного модульного теста?

Я ищу что-то вроде следующего:

[Test] 
public response_from_database_unit_test_equals_111291() 
{ 
//call the database unit test 
//retrieve value from database unit test 
} 
+0

Вы используете код Entity Framework сначала как ваш уровень доступа к данным, без каких-либо хранимых процедур? если да, то есть фантастический способ провести тестирование данных, не ударяя базу данных, но со 100% -ной надежностью слоя данных. дай мне знать. –

+0

Я не так люблю слушать, как это делается –

+0

от «this way» Я предполагаю, что вы имели в виду ваш вопрос, поэтому я ответил, что –

ответ

1

А вот дополнительный ответ вы запросили, основываясь на чисто Entity Framework

[TestMethod] 
    public void GetAllBlogs_Orders_By_Name() 
    { 
     var data = new List<Blog> 
     { 
      new Blog { Name = "BBB" }, 
      new Blog { Name = "ZZZ" }, 
      new Blog { Name = "AAA" }, 
     }.AsQueryable(); 

     var mockSet = new Mock<DbSet<Blog>>(); 

     mockSet.As<IQueryable<Blog>>().Setup(m => m.Provider).Returns(data.Provider); 
     mockSet.As<IQueryable<Blog>>().Setup(m => m.Expression).Returns(data.Expression); 
     mockSet.As<IQueryable<Blog>>().Setup(m => m.ElementType).Returns(data.ElementType); 
     mockSet.As<IQueryable<Blog>>().Setup(m => m.GetEnumerator()).Returns(0 => data.GetEnumerator()); 

     // we tell EF that treat our data list as the table of Blogs. 
     var mockContext = new Mock<BloggingContext>(); 
     mockContext.Setup(c => c.Blogs).Returns(mockSet.Object); 

     // make EF query the blogs table (i.e. our list) 
     var context = mockContext.Object; 

     // EF has queried our list here 
     // you could run Select, OrderBy, Where etc. as well 
     var blogs = context.Blogs.ToList(); 

     Assert.AreEqual(3, blogs.Count); 
     Assert.AreEqual("AAA", blogs[0].Name); 
     Assert.AreEqual("BBB", blogs[1].Name); 
     Assert.AreEqual("ZZZ", blogs[2].Name); 
    } 

я не писал этот образец. он прямо из https://msdn.microsoft.com/en-us/library/dn314429.aspx (так что все кредит MSDN)

Дело в том, что с 0% участием базы данных мы позволили Entity Framework знать, что «эй EF! Tre в моем списке как таблица. " EF затем запускает все ваши запросы (Where, Select, OrderBy, GroupBy и т. д.) в вашем списке. И это так тривиально, чтобы настроить этот список. (включая вложенные ссылки)

Ваш код слоя данных всегда будет охватываться этим модульным тестированием. И вы можете доверять EF, чтобы делать правильные вызовы SQL, когда задействована фактическая таблица.

p.s. только 2 вещи, которые я ищу - это предложения Include и DbFunctions. Эти 2 ведут себя по-разному между локальными списками и фактическими таблицами. Но как только вы будьте осторожны с этими двумя вещами, это восхитительная вещь, чтобы протестировать ваш уровень данных в такой степени, не беспокоясь о реальной базе данных вообще.

+0

Это потрясающе, но в какой момент вы можете запустить запрос выбора к своим данным? –

+0

Я не знаю человека, который действительно борется с этим: https://drive.google.com/file/d/0ByqKtGmtuLzZUGVNVkdVaDYzOGc/view?usp=drivesdk –

+0

вы неправильно настроили Устройства .. используйте этот var mockContext = new Тестовая модель (); mockContext.Setup (c => c.Devices) .Returns (mockSet.Object); –

1

Если вы хотите сделать тестирование базы данных родственными, то есть несколько вариантов, которые делают его более легким для вас. (Это не будет 100% морщин бесплатно, поскольку тестирование БД не тривиально)

  1. в [Setup] методе тестового класса, установка нового Scope транзакций и настройка любых предпосылки вам нужно. (наличие или отсутствие записи)
  2. в фактическом тестовом случае выполните вашу проверку с помощью Linq2Sql или EF LINQ. он очень продуктивен и позволяет избежать неприятных SQL/хранимых процедур.
  3. в методе [Teardown], заполните область действия для совершения транзакции.

при любом исключении сделка будет естественным образом откатываться назад.

И вместо одного теста тестирования тестовых модулей базы данных выведите общий код в общие методы и назовите их как ваши тесты базы данных, так и эти тесты. (например, GetRecordWithId (5678))

Таким образом, ваши тесты действительно не зависят от тестов модулей базы данных, но совместно используют код доступа к данным.

И как вы упомянули правильно, это не имеет значения, что вы называете это .. они, возможно, тестирование данных или тестирование интеграции и т.д. (не обязательно модульных тестов)

Мы можем сделать все возможное, чтобы сохранить состояние база данных очищается с использованием области транзакций, но в конечном итоге проблемы с подключением, параллельное выполнение теста, выполнение тестов на серверах dev, подключающихся к общему серверу данных (или предварительные результирующие требования локального SQL-сервера), выполнение теста на сервере сборки и т. д. создают проблемы, когда дело доходит до при тестировании базы данных.

Многие команды используют стратегию создания новой базы данных, специфичной для тестового прогона [prefix + timestamp], чтобы она не сталкивалась с другими прогонами. И оторвите дБ в конце его. (в худшем случае есть фоновый процесс, который отслеживает базы данных с определенным именем префикса и очищает его каждую полуночи, основываясь на временной отметке. Как вы можете видеть, существует много периферийной работы, поскольку ценность тестирования слой данных.

+0

Благодарю вас, как всегда за ваш добрый, тщательный отзыв. не могли бы вы указать мне пример, показывающий этот тип тестирования от начала до конца или, возможно, только [setup]? –

+0

raja Я был бы очень признателен, если бы вы могли также включить пример с использованием области транзакций –

+0

это поможет? http://stackoverflow.com/questions/321180/how-do-i-test-database-related-code-with-nunit –

Смежные вопросы