Jak przetestować kod związany z bazą danych za pomocą NUnit?
Chcę napisać testy jednostkowe z NUnit, które trafiły do bazy danych. Chciałbym mieć bazę danych w spójnym stanie dla każdego testu. Myślałem, że każdy test pozwoli mi "cofnąć" więc przeszukałem i znalazłem kilka artykułów z lat 2004-05 na temat:
- http://weblogs.asp.net/rosherove/archive/2004/07/12/180189.aspx
- http://weblogs.asp.net/rosherove/archive/2004/10/05/238201.aspx
- http://davidhayden.com/blog/dave/archive/2004/07/12/365.aspx
- http://haacked.com/archive/2005/12/28/11377.aspx
Te wydają się rozwiązywać wokół implementacji niestandardowego atrybutu dla NUnit, który buduje zdolność do wycofywania operacji DB po każdym teście wykonuje.
To świetnie, ale...
- czy ta funkcjonalność istnieje gdzieś w NUnit natywnie?
- czy ta technika została ulepszona w ciągu ostatnich 4 lat?
- czy to nadal najlepszy sposób na testowanie kodu związanego z bazą danych?
Edit: nie chodzi o to, że chcę dokładnie przetestować mój DAL, ale bardziej o to, że chcę przetestować fragmenty mojego kodu, które wchodzą w interakcję z bazą danych. Aby te testy były" bez dotykania " i powtarzalne, byłoby super, gdybym mógł zresetuj bazę danych po każdym z nich.
Co więcej, chcę uprościć to do istniejącego projektu, który w tej chwili nie ma miejsca na testy. Z tego powodu nie mogę praktycznie stworzyć bazy danych i danych od podstaw dla każdego testu.
5 answers
NUnit ma teraz atrybut [Rollback], ale wolę zrobić to w inny sposób. Używam klasy TransactionScope . Można go użyć na kilka sposobów.
[Test]
public void YourTest()
{
using (TransactionScope scope = new TransactionScope())
{
// your test code here
}
}
Ponieważ nie powiedziałeś TransactionScope, aby zatwierdził, zostanie automatycznie wycofany. Działa nawet wtedy, gdy twierdzenie nie powiedzie się lub zostanie wyrzucony inny wyjątek.
Innym sposobem jest użycie [SetUp] do utworzenia TransactionScope i [TearDown] do wywołania Dispose na nim. Eliminuje powielanie kodu, ale / align = "left" /
[TestFixture]
public class YourFixture
{
private TransactionScope scope;
[SetUp]
public void SetUp()
{
scope = new TransactionScope();
}
[TearDown]
public void TearDown()
{
scope.Dispose();
}
[Test]
public void YourTest()
{
// your test code here
}
}
Jest to tak samo bezpieczne jak instrukcja using w indywidualnym teście, ponieważ NUnit zagwarantuje, że zostanie wywołane Tearddown.
Mimo wszystko uważam, że testy, które trafiły do bazy danych, nie są tak naprawdę testami jednostkowymi. Nadal je piszę, ale myślę o nich jak o testach integracyjnych. Nadal uważam je za wartościowe. Jednym z miejsc, z których często korzystam, jest testowanie kodu LINQ do SQL. Nie używam projektanta. Ręcznie piszę DTO i atrybuty. Byłem wiadomo, że się myli. Testy integracyjne pomagają złapać mój błąd.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-19 21:16:24
Właśnie poszedłem do grupy użytkowników. NET i prezenter powiedział, że użył SQLlite w konfiguracji testowej i tearddown i użył opcji in memory. Musiał trochę przesunąć połączenie i wyraźnie zniszczyć połączenie, ale za każdym razem dawało czyste DB.
Http://houseofbilz.com/archive/2008/11/14/update-for-the-activerecord-quotmockquot-framework.aspx
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-26 16:07:32
Do tego typu testów eksperymentowałem z NDbUnit (współpracując z NUnit). Jeśli pamięć służy, był to port DbUnit z platformy Java. Miał wiele sprytnych poleceń dla tego rodzaju rzeczy, które próbujesz zrobić. Wydaje się, że projekt przeniósł się tutaj:
Http://code.google.com/p/ndbunit/
(kiedyś było na http://ndbunit.org).
Źródło wydaje się być dostępne za pośrednictwem tego link: http://ndbunit.googlecode.com/svn/trunk/
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-26 16:09:42
Nazwałbym te testy integracyjne, ale nieważne. To, co zrobiłem dla takich testów, to moje metody konfiguracji w klasie testowej wyczyść wszystkie tabele zainteresowania przed każdym testem. Generalnie ręcznie piszę SQL, aby to zrobić, aby nie używać klas testowanych.
Generalnie polegam na ORM dla mojego datalayera i dlatego nie piszę tam zbyt wiele testów jednostkowych. Nie czuję potrzeby testowania kodu, którego nie piszę. Do kodu, który dodaję w warstwie, zazwyczaj używam dependency injection, aby wyodrębnić rzeczywiste połączenie z bazą danych, tak aby podczas testowania kodu nie dotykał on rzeczywistej bazy danych. Zrób to w połączeniu z szyderczymi ramami dla najlepszych wyników.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-26 16:12:08
Rozważ stworzenie skryptu bazy danych, aby można było uruchamiać go automatycznie z NUnit, jak również ręcznie dla innych typów testów. Na przykład, jeśli używasz Oracle, Uruchom SqlPlus z NUnit i uruchom Skrypty. Skrypty te są zwykle szybsze do napisania i łatwiejsze do odczytania. Ponadto, co bardzo ważne, uruchamianie SQL z Toad lub jego odpowiednika jest bardziej pouczające niż uruchamianie SQL z kodu lub przechodzenie przez ORM z kodu. Ogólnie stworzę zarówno skrypt setup jak i tearddown i umieść je w metodach setup i tearddown.
Czy powinieneś w ogóle przechodzić przez DB z testów jednostkowych to kolejna dyskusja. Uważam, że często ma to sens. Dla wielu aplikacji baza danych jest absolutnym centrum działania, logika jest wysoce ustawiona, a wszystkie inne technologie, Języki i techniki przechodzą duchy. A wraz z rozwojem języków funkcyjnych zaczynamy zdawać sobie sprawę, że SQL, podobnie jak JavaScript, jest w rzeczywistości wielkim językiem, który był przez te wszystkie lata pod naszym nosem.
Tak na marginesie, Linq do SQL (co lubię w koncepcji, choć nigdy nie używane) wydaje mi się prawie jak sposób, aby zrobić surowy SQL z kodu bez przyznania się do tego, co robimy. Niektórzy ludzie lubią SQL i wiedzą, że go lubią, inni lubią go i nie wiedzą, że go lubią. :)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-07 20:46:03