2014-11-05 10 views
5

Obecnie staram się zrozumieć, jak działają adnotacje @Injectable i @Tested. Zrobiłem już kilka testów i zrozumiałem tę koncepcję, ale nie wiedziałem, w jaki sposób mogę korzystać z tej funkcjonalności w rzeczywistych aplikacjach. Załóżmy, że tworzymy klasę tłumaczeń językowych, która zależy od usługi sieciowej. Metody usług internetowych są obudowane w klasie serparate:Jak wstrzykiwać wyśmiewane zależności za pomocą jmockit

// class to test 
public class Translator() { 
    private TranslatorWebService webService; 

    public String translateEnglishToGerman(String word){ 
     webService = new TranslatorWebService(); 
     return webService.performTranslation(word); 
    } 
} 

// dependency 
public class TranslatorWebService { 
    public String performTranslation(String word){ 
    // perform API calls  
    return "German Translation"; 
    } 
} 

Aby przetestować klasę Translator niezależnie chcielibyśmy mock klasy TranslatorWebService. Według mojego rozeznania, klasa Test Shoud wyglądać następująco:

public class TranslatorTest { 
    @Tested private Translator tested; 
    @Injectable private TranslatorWebService transWebServiceDependency; 

    @Test public void translateEnglishToGerman() { 
     new Expectations() {{ 
      transWebServiceDependency.performTranslation("House"); 
      result = "Haus"; 
     }}; 

     System.out.println(tested.translateEnglishToGerman("House")); 
    } 
} 

Kiedy ten przypadek testowy wykonywany po raz pierwszy, spodziewałem wynik „Haus”. Na drugi rzut oka zobaczyłem, że linia zawsze nadpisuje wstawioną symulowaną instancję rzeczywistą instancją. Ale jak mogę uniknąć tego zachowania bez zmiany logiki biznesowej?

Odpowiedz

6

Dobre pytanie. Rzeczą, o której należy pamiętać, że JMockit (lub inne fałszywe API) obsługuje wtrysk zależności, jest to, że ma być używany tylko wtedy, gdy testowany kod faktycznie polega na wstrzyknięciu jego zależności.

Przykład: klasa Translator ma wartość , a nie polega na iniekcji dla zależności zależnej od TranslatorWebService; zamiast tego uzyskuje ją bezpośrednio poprzez instancję wewnętrzną.

więc w takiej sytuacji po prostu można drwić zależność:

public class TranslatorTest { 
    @Tested Translator tested; 
    @Mocked TranslatorWebService transWebServiceDependency; 

    @Test public void translateEnglishToGerman() { 
     new Expectations() {{ 
      transWebServiceDependency.performTranslation("House"); 
      result = "Haus"; 
     }}; 

     String translated = tested.translateEnglishToGerman("House"); 

     assertEquals("Haus", translated); 
    } 
} 
+0

Dzięki za odpowiedź. Nie wiedziałem, że wstrzyknie się również obiekty "@ Mocked". Zgodnie z dokumentacją tylko obiekty '@ Injectable' obsługują tę funkcję:' Aby wykonać iniekcję, klasa testowa musi również zawierać jedno lub więcej fałszywych pól lub fałszywych parametrów zadeklarowanych jako @Injectable. Próbne pola/parametry opatrzone adnotacją @Mocked lub @Capturing nie są przeznaczone do wstrzykiwania. "(Oficjalne dokumenty: http://jmockit.github.io/tutorial/BehaviorBasedTesting.html#tested) Ale i tak to rozwiązanie działa dla mnie . Dziękuję Ci bardzo! –

+1

Obiekty '@ Mocked' są * nie * wstrzykiwane; ich klasy są kpione. –

+1

Chciałem tylko zwrócić uwagę, że w tym przypadku, ustawiając oczekiwanie, że usługa internetowa zwróci "Haus" i potwierdzając, że podmiot testowy zwraca "Haus", naprawdę nie osiągnęliśmy większego wyniku testu. Odpowiedź na temat używania @Mocked jest poprawna, ale dla mnie ważniejsze wydaje się upewnienie się, że faktycznie uzyskaliśmy jakiś użyteczny test, więc chciałbym zaproponować, aby temat badania został zrestrukturyzowany * lub * test został zmieniony, aby zweryfikować jedynie, że test temat wywołuje usługę sieciową z oczekiwanym parametrem. – unigeek

Powiązane problemy