2017-02-22 7 views
1

Ich habe ziemlich viele Artikel/Blog/StackOverflow Fragen gelesen, aber die Verwirrung in Bezug auf Mockito Mock und Spion bleibt noch. Also habe ich angefangen, sie in einer kleinen Spring Boot App zu implementieren. Meine App hat eine ProductRepository Verlängerung CrudRepository.Mockito Mock und Spy in SpringBoot App

Derzeit teste ich das Repository von ProductRepository spöttisch als

@RunWith(SpringRunner.class) 
    @SpringBootTest(classes = {RepositoryConfiguration.class}) 
    public class ProductRepositoryMockTest { 

    @Mock 
    private ProductRepository productRepository; 
    @Mock 
    private Product product; 

    @Test 
    public void testMockCreation(){ 
     assertNotNull(product); 
     assertNotNull(productRepository); 
    } 

    @Test 
    public void testSaveProduct() { 
     assertThat(product.getId(), is(equalTo(0))); 
     when(productRepository.save(product)).thenReturn(product); 
     productRepository.save(product); 
     //Obviously this will fail as product is not saved to db and hence 
     //@GeneratedValue won't come to play 
     //assertThat(product.getId() , is(not(0))); 
    } 

    @Test 
    public void testFindProductById() { 

     when(productRepository.findOne(product.getId())).thenReturn(product); 
     assertNotNull(productRepository.findOne(product.getId())); 
     assertEquals(product, productRepository.findOne(product.getId())); 
    } 
    } 

Der Test besteht folgt. Ist das der richtige Weg? Ich möchte auch verstehen, wie man hier @Spy verwendet und warum sollte ich es brauchen? Alle diesbezüglichen spezifischen Szenarien sind sehr willkommen.

Vielen Dank im Voraus.

+1

Testen Sie nicht Ihre Repositories. Konzentrieren Sie sich auf die Serviceebene bezüglich Komponententests. Wenn Sie etwas Logik in Ihrem Repository haben, dann ist das wahrscheinlich ein Designfehler. –

+0

Ja, habe den Punkt verstanden. Vielen Dank. – user2693135

+0

@Maciej Kowalski Schließlich gelang es, Mocks und Spione basierend auf Ihren Eingaben zu verwenden, um die Service-Schicht zu testen. Aber weiß nicht, ob ich es richtig gemacht habe, Mein Repo ist https://github.com/ximanta/mockito_spy_example Ihre Beobachtungen werden wertvoll sein. Bei Bedarf kann dies als Frage gepostet werden. Vielen Dank. – user2693135

Antwort

2

Ich habe einen Blick auf Ihren Tests gemacht und es gibt nur wenige Dinge im Auge zu behalten (dies meiner Erfahrung basiert, so der letzte Aufruf an Sie):

1) hamcrest - Wenn das ist möglich, ich würde dringend empfehlen, Hamcrest für Ihre Assert-Implementierungen zu verwenden. Erstens ist es viel vielseitiger und vielseitiger als die Standard-Junit-Assertions. Zweitens könnte man eines Tages die Notwendigkeit haben (wie ich bei einem meiner Projekte) von Junit zu Testng für Beispiel zu wechseln. Da alle Ihre Behauptungen auf einer xunit-neutralen Implementierung basieren, wird der Wechsel nicht so schmerzhaft sein.

2) Assertions - Statt assertNull, geht assertEquals für den assertThat(String description, T value, Mathcer<T> matcher); Dank des hamcrest an, dass Sie klare Fehlermeldungen, wenn ein Test Pause bekommen.

3) Kleine Tests - In Ihrem Repository-Test .. nicht alle Fälle in einem Test. Versuchen Sie, viele kleine und einfache Tests für Fälle wie: findOne .. count .. findAll usw. zu erstellen. Wieder wird es einfacher sein, das Problem zu finden, wenn ein kleiner Test wie dieser bricht. Und wenn mehr Fälle kommen Sie nicht mit mehr als 200 Zeilen eines Testfall am Ende der

4) Naming nicht akzeptabel ist - Sie Ihre Tests nicht benennen .. testXYZ. Es ist offensichtlich, dass dies Testmethoden sind. Ich würde empfehlen, die BDD Art der Benennung: shouldX_whenY_givenZ. F.E. shouldReturnZeroCount_givenNoEntitiesInTheDatabase

5) Struktur - Versuchen Sie jede Ihrer Testimplementierung in drei explizite Abschnitte aufzuteilen, einschließlich Kommentare für das beste Ergebnis:

public void should..() throws Exception{ 
     // Arrange 

      // when().then() 
      // mock() 

     // Act 

      // classUnderTest.process() 

     // Assert 

      // assertThat(..) 
    } 

6) nicht Ihre Testklassen zwischen Mock Split/Spionagetest. Habe einen ImplTest.

7) Nie eine Klasse, die Sie testen. Im schlimmsten Fall verwenden Sie Spy, wenn Sie einige der Methoden der zu testenden Klasse vortäuschen müssen. Der spöttische Punkt besteht darin, die Implementierung in der getesteten Klasse zu isolieren, so dass während des Tests nur diese Klassenlogik aufgerufen wird. Mock nur Abhängigkeiten der Klasse.

+0

Danke. Die Dinge sind jetzt klar. – user2693135

+0

Gibt es Überlegungen, warum die InjectMock-Annotation im Vergleich zur Initialisierung des zu testenden Objekts mit Mocks, die die Konstruktor/Setter-Methode verwenden, nicht empfohlen wird? – user2693135

+0

wird tatsächlich gefördert. Macht den Test-Code klarer –