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:

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...

  1. czy ta funkcjonalność istnieje gdzieś w NUnit natywnie?
  2. czy ta technika została ulepszona w ciągu ostatnich 4 lat?
  3. 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.

Author: abatishchev, 2008-11-26

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.

 68
Author: Mike Two,
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

 3
Author: nportelli,
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/

 1
Author: Scott Lawrence,
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.

 1
Author: tvanfosson,
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ą. :)

 0
Author: Mike,
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