2009-07-06 10 views
7

PrzykładCzy muszę napisać test jednostkowy dla metody w klasie usług, która wywołuje tylko metodę w klasie repozytoriów?

mam klasy repozytorium (DAL)

public class MyRepository : IMyRepository 
{ 
    public void Delete(int itemId) 
    { 
     // creates a concrete EF context class 
     // deletes the object by calling context.DeleteObject() 
    } 

    // other methods 
} 

również mieć klasę usług, (bil)

public class MyService 
{ 
    private IMyRepository localRepository; 

    public MyService(IMyRepository instance) 
    { 
     this.localRepository = instance; 
    } 

    public void Delete(int itemId) 
    { 
     instance.Delete(itemId); 
    } 

    // other methods 
} 

Tworzenie test jednostki do MyRepository zajęłoby znacznie więcej czasu niż wdrożenie, ponieważ musiałbym kpić z kontekstu Entity Framework.

Jednak tworzenie testu jednostkowego dla usługi MyService wydaje się bzdurą, ponieważ wywołuje tylko repozytorium. Mogę tylko sprawdzić, czy rzeczywiście wywołał metodę usuwania repozytorium.

Pytanie

Jak proponujesz do badanej jednostki te parę metod usunąć. Obie? Jeden? Żaden? A co byś przetestował?

Odpowiedz

1

Tak, zdecydowanie napiszę test jednostkowy dla warstwy serwisowej. Powodem tego jest to, że nie testujesz tylko, czy twoja implementacja działa teraz, ale testujesz także, że będzie działała w przyszłości.

Jest to niezbędna koncepcja do zrozumienia. Jeśli ktoś przyjdzie później i zmieni Twój ServiceLayer, a nie ma testu jednostki, jak możesz sprawdzić, czy funkcjonalność działa dalej?

Chciałbym również napisać testy dla twojego DAL, ale umieściłbym je w osobnym zespole zwanym DataTests lub coś takiego. Celem tutaj jest odizolowanie twoich obaw od złożeń. Testy jednostkowe nie powinny w rzeczywistości dotyczyć twojego DAL.

+0

Ale jeśli testuję metodę Service.Delete(), wszystko, co mogę zrobić, to sprawdzić, czy wywołuje ona metodę Repository.Delete(). Nie mogę sprawdzić żadnych danych, ponieważ manipulowanie danymi odbywa się w repozytorium. Inne (przyszłe) zawiłości nie zostaną uwzględnione w teście. –

+1

@Robert To nie do końca poprawne. Będziesz musiał stworzyć fałszywy obiekt IMyRepository. Gdy to zrobisz, możesz skonfigurować próbę, aby po wywołaniu warstwy usługi usuwać na niej, możesz sprawdzić, czy usuwanie jest wywoływane na fałszywej próbce. Dlatego testujesz funkcjonalność Service.Delete bez testowania Repository.Delete. – Joseph

1

Tak, jedno i drugie.

IMyRepository mock = ...; 
// create Delete(int) expectation 

MyService service = new MyService(mock); 
service.Delete(100); 

// Verify expectations 

Teraz Twoja metoda usuwania może wywoływać tylko metodę Delete w repozytorium, ale to nie znaczy, że zawsze będzie. Chcesz przeprowadzić testy jednostkowe, aby częściowo zweryfikować, czy zachowuje się poprawnie, a częściowo jako sposób zdefiniowania specyfikacji działania repozytorium.

Musisz również mieć test, który sprawdzi, czy konstruktor rzuci wyjątek, jeśli repozytorium ma wartość NULL. W tej metodzie można również wykonać inne sprawdzanie poprawności, takie jak nieujemne identyfikatory lub niezerowy identyfikator. Być może tak się nie dzieje, należy do specyfikacji, tworząc testy, które sprawdzają oczekiwane zachowania.

Wydają się być banalne, ale mogę zagwarantować, że zmieni się jeden dzień, a twoje oczekiwania i specyfikacje mogą nie zostać zweryfikowane.

+0

Cóż, wszystko, co zrobiłeś w swoim przykładzie, to test Service.Delete(). Kpiłeś z mojego repozytorium i przetestowanej usługi, którą faktycznie wywołuje w repozytorium. –

+0

Co mam na myśli z moim poprzednim komentarzem, to że powiedziałeś "oba", ale napisałeś kod, aby przetestować warstwę usługi. Ale tak, usługa jest testowana w twoim przypadku. –

+0

Przepraszam, tak, miałbym wtedy kolejny zestaw testów do testowania konkretnego repozytorium, co może być trudniejsze, ponieważ prawdopodobnie jesteś zależny od bibliotek zewnętrznych i innych warstw. Te testy mogą być bardziej podobne do testów integracyjnych. Tak więc obaj dążą do całkowitego pokrycia kodu. Ale nie sądzę, że możesz zaniedbać tę klasę, ponieważ jest to abstrakcja, z której będziesz kodować swoją aplikację. –

0

Utwórz test dla usługi. Obecnie wystarczy wywołać metodę usuwania repozytorium; jednak nie powinieneś o to dbać. Co, jeśli później coś się stanie i funkcjonalność stanie się o wiele bardziej skomplikowana? Czy nie chcesz mieć kodu testu jednostkowego, który zapewni, że funkcjonalność nadal działa zgodnie z oczekiwaniami?

Jeśli ujawniasz swoje usunięcie przez swoją usługę, spodziewasz się, że będzie to miało skutek. Napisz test jednostkowy, aby przetestować ten efekt. W zależności od twoich konkretnych potrzeb, powiedziałbym, że nie musisz mieć testu w Kasie repozytorium, szczególnie jeśli ta funkcjonalność jest wykonywana jako część funkcji Service Delete, ale to naprawdę zależy od tego, jaki poziom pokrycia masz " Próbuję.

+0

Ale jeśli testuję metodę Service.Delete(), wszystko, co mogę zrobić, to sprawdzić, czy wywołuje ona metodę Repository.Delete(). Nie mogę sprawdzić żadnych danych, ponieważ manipulowanie danymi odbywa się w repozytorium. –

+0

Czy wystarczy wiedzieć, że Service.Delete() wywołań Repository.Delete()? W takim razie wystarczy tylko Service.Delete(). Czy chcesz sprawdzić dane? Będziesz potrzebował trochę szyderstwa, aby sprawdzić, czy dane zostały zmodyfikowane. –

0

Ponadto, gdybyś utworzył ten kod z TDD, miałbyś test. To naprawdę ma znaczenie, czy ludzie mogą wywoływać Delete za pośrednictwem swojej usługi, więc faktycznie musicie to przetestować.

0

Moim zdaniem musisz przetestować oba. Być może możesz stworzyć klasę kontekstu EF EF w oddzielnej fabryce, którą można przetestować łatwiej i sfałszować klasę kontekstu testów MyRepository. To będzie łatwiejsze, a korzystanie z fabryki do tworzenia wywołań kontekstowych wydaje mi się bardzo przydatne.

+0

Chciałbym, ale jak mogę google w sieci, szydercze Entity Framework kontekście jest ból w ... –

Powiązane problemy