2009-12-21 11 views
5

Jestem nowy w Kpiącym i trochę obeznanym z testowaniem jednostkowym i ostatecznie zdecydowałem się ugryźć bullet na nowym projekcie rozpoczynającym się od przodu z surowym podejściem TDD. Mam jednak jedną klasę usług i metodę, którą muszę retrospektywnie dodać do testów, ponieważ została ona wypromowana z prototypu.Usługa Testu Jednostek, która ma wywołanie WCF (MSUnit + Moq)

nie wiem od czego zacząć, choć na tym konkretnym teście, to klasy i metody zaangażowany:

public class PageService : IPageService 
{ 
    private readonly ITestService testServiceClient; 

    public PageService(ITestService testServiceClient) 
    { 
     this.testServiceClient = testServiceClient; 
    } 

    public Page GetPage(Guid websiteId, string pageKey) 
    { 
     Page builtPage = null; 

     // WCF SERVICE CALL I DO NOT WANT EXECUTING WHEN RUNNING UNIT TEST 
     // BUT RATHER WANT A BLANK NEW INSTANCE OF "PAGE" CREATED USING MOQ?? 
     var page = testServiceClient.GetPage(websiteId, pageKey); 

     if (page == null) 
      return null; 

     builtPage = new Page(); 

     [code here to build builtPage if input params ok] ... 

     return builtPage; 
    } 
} 

Co Usiłuję zrobić, to napisać jeden test, z tym mam nadzieję, że mogę rozwijać wszystkie permutacje z testów GetPage(...), ale dla pierwszego testu wystarczy przetestować, czy poprawne websiteId i pageKey zostało przekazane, jeśli tak, otrzymają prawidłową instancję z powrotem i potwierdzą prawdziwość testu jednostkowego.

testServiceClient jest klientem usługi WCF, który był wcześniej zawarty w oświadczeniu using(), ale usunąłem go z tego, mając nadzieję, że będzie to działało z zastrzykiem zależności, ponieważ uważam, że będzie to pierwszy krok wymagany do testowania, z tego, co rozumiem, będę musiał zrobić z niego fałszywkę/wyśmiać? klient wcf zamiast, gdzie testServiceClient.GetPage() zwraca znany zestaw danych w pamięci? Mam nadzieję, że jestem na dobrej drodze.

Więc tutaj jest moje początkowe plany mojego testów jednostkowych (Używam Moq ramy, Setup() jest nowa wersja Expect() jeśli nie wykorzystali najnowszą ver z Min):

/// <summary> 
/// Tests service returns a valid instance of type `Page` when a valid website and valid page key is tested. 
/// </summary> 
[TestMethod] 
public void Test_Valid_Website_And_Valid_PageKey_Returns_Valid_Instance_Of_Page() 
{ 
    // Arrange 
    Page page = null; 

    // Act 
    var newPage = new Page() { Title = "Mocked Version!?"}; 

    testServiceClient = new Mock<ITestService>(); 
    testServiceClient.Setup(x => x.GetPage(websiteId, "about-us")).Returns(newPage); 

    service = new PageService(testServiceClient.Object); 
    page = service.GetPage(websiteId, "about-us"); 

    // Assert 
    Assert.IsInstanceOfType(page, typeof(Page), "Object was not of expected instance type."); 
} 

ja nie mam pomysł, dokąd się udać, czy jestem na dobrej drodze? Mogę potwierdzić powyższe nie ma błędów składniowych, a ja nie otrzyma wyjątek:

System.ArgumentException: Invalid setup on a non-overridable member: 
x => x.GetPage(websiteId, "about-us"). 

Wiem tylko, że chcę moje service.GetPage(...) zwrócić nową instancję, jak websiteId i pageKey była ważna, jednak I don” Chcę używać prawdziwego wywołania WCF testServiceClient.GetPage() ... mam nadzieję, że rozumiem ideę kpiny poprawnie. Czy powiedziałem to poprawnie poprzez Moq, gdy używasz usługi testServiceClient.GetPage w tej usłudze, w rzeczywistości po prostu zwracasz nową instancję strony?

Wszelkie wyjaśnienia są mile widziane! Dzięki chłopaki!

Odpowiedz

4

Powiedziałbym, że jesteś na dobrej drodze. Jeśli ITestService naprawdę jest interfejsem (jak wskazuje jego nazwa), będziesz mógł go sfałszować.

Jednak podczas definiowania ustawień, Moq musi być w stanie określić, którą metodę miałeś na myśli, i wydaje się, że w jakiś sposób wskazujesz na metodę, która nie istnieje w interfejsie.

Nie pokazują nam interfejs ITestService, a nie wiemy, typ zmiennej websiteId.

Jeśli przyjrzeć się bliżej na metodzie konfiguracji widać, że to naprawdę sposób ogólny, więc nie typ wnioskowania dzieje, gdy nazywają go bez parametrów ogólnych.

Domyślam się, że deklaracja websiteId jakoś kłóci się z deklaracją GetPage.Jeśli, na przykład, websiteId został uznany jako object, Moq wyglądałby po metody z tego podpisu:

Page GetPage(object x, string y); 

który nie jest taki sam jak

Page GetPage(Guid x, string y); 

w każdym przypadku, gdy uda się sprawić, aby Instalator działał, twoje podstawowe zdanie na temat testu jednostki wydaje się być w porządku. Można zrobić więcej niż po prostu stwierdzając, że instancja nie jest nieważna, ponieważ Mock zapewni, że wystąpienie zwrócony jest taka sama jak w przypadku ty originall konfigurowaniu:

[TestMethod] 
public void Test_Valid_Website_And_Valid_PageKey_Returns_Valid_Instance_Of_Page() 
{ 
    // Arrange 
    Page page = null; 

    // Act 
    var newPage = new Page() { Title = "Mocked Version!?"}; 

    testServiceClient = new Mock<ITestService>(); 
    testServiceClient.Setup(x => x.GetPage(websiteId, "about-us")).Returns(newPage); 

    service = new PageService(testServiceClient.Object); 
    page = service.GetPage(websiteId, "about-us"); 

    // Assert 
    Assert.AreEqual(newPage, page); 
} 

zauważy znacznie cenniejszego dochodzić.

+0

+1 Dobra odpowiedź - @GONeale, tylko po to, aby potwierdzić, co mówi Mark, przeprowadziłem szybki test za pomocą MOQ i interfejsu, który zwraca stronę - działa dobrze. Wydaje się, że zamiast tego robisz coś takiego, jak mockowanie konkretnej instancji, w której GetPage nie jest deklarowane jako wirtualne. –

+0

Cześć chłopaki, dziękuję za poświęcenie czasu na przeczytanie mojego posta. Cóż, ITestService jest klientem usługi generowanej przez WCF (projekt prawym przyciskiem myszy -> dodaj nazwę referencyjną usługi). W związku z tym nie sądzę, że mogę zadeklarować go jako "wirtualny", ponieważ jest to klasa generowana automatycznie. Mógłbym jednak stworzyć prostą klasę wywołującą WCF i uczynić ją wirtualną, czy mogłoby to pomóc w twoim przypadku? Dzięki za wskazówkę Assert. – GONeale

+0

Czy rozumiem poprawnie mówiąc przez deklarowanie 'testServiceClient.Setup (x => x.GetPage (..)). Zwroty (newPage)' mówi każde wywołanie nazwy tej metody (zagnieżdżone nawet jako metoda obiektu przekazywana przez jako parametr, taki jak przykład 'new PageService (testServiceClient.Object)'), aby faktycznie nie uruchomić metody * actual * (wcf), ale po prostu zwrócić instancję 'newPage' zamiast tego? Czy właśnie dlatego 'virtual' jest wymagany, zastępuje go całkowicie nową zawartością metody? – GONeale

Powiązane problemy