2017-10-13 16 views
0

Wir streiten mit meinen Kollegen über diesen Ansatz. Sie sagen, SpringRunner nur auf Integrations- oder Funktionsebenen zu verwenden.Ist es in Ordnung, SpringRunner in Komponententests zu verwenden?

Die Frage ist, welche Vor- und Nachteile der Verwendung in Ebene unten?

Zum Beispiel habe ich einfach Bohne:

public class RewardDurationCalculator { 

    private Clock clock; 

    public OptionalLong calculate(DurationType durationType, List<Pass> passes) { 
     long now = Instant.now(clock).getEpochSecond(); 
     switch (durationType) { 
      case FULL_PASS: 
       return getCurrentPassDuration(passes, now); 
      case TILL_THE_END_OF_THE_CURRENT_ACTIVE_PASS: 
       return getTimeInCurrentPassLeft(passes, now); 
     } 
     return OptionalLong.empty(); 
    } 

    private OptionalLong getCurrentPassDuration(List<Pass> passes, long now) { 
     return passes.stream() 
       .filter(currentPass(now)) 
       .mapToLong(Pass::getDuration) 
       .findFirst(); 
    } 

    private OptionalLong getTimeInCurrentPassLeft(List<Pass> passes, long now) { 
     return passes.stream() 
       .filter(currentPass(now)) 
       .mapToLong(pass -> getEndTs(pass) - now) 
       .findFirst(); 
    } 

    private Predicate<Pass> currentPass(long now) { 
     return pass -> pass.getStartTs() >= now && now <= getEndTs(pass); 
    } 

    private long getEndTs(Pass pass) { 
     return pass.getStartTs() + pass.getDuration(); 
    } 

} 

, die einige Berechnungslogik tut. Denn es haben, lasse ich auch config:

@Configuration 
public class RewardDurationCalculatorConfiguration { 

    @Bean 
    public RewardDurationCalculator rewardDurationCalculator(Clock clock) { 
     return new RewardDurationCalculator(clock); 
    } 

} 

Warum also nicht schreiben kann ich Unit-Test für es wie folgt aus:

@RunWith(SpringRunner.class) 
@ContextConfiguration(classes = RewardDurationCalculatorConfiguration.class) 
public class RewardDurationCalculatorTest { 

    @MockBean 
    private Clock clock; 
    @Autowired 
    private RewardDurationCalculator rewardDurationCalculator; 

    @Test 
    public void testCalculateCurrentPassDurationShouldBeReturnedIfPassWasCreatedRightNow() { 
     rewardDurationCalculator.calculate(DurationType.FULL_PASS, Collections.emptyList()); 
    } 

} 

Welche Nachteile ich mit der Verwendung solcher Ansatz stellen kann?

Antwort

4

Ich stimme eher mit Ihren Kollegen überein.

Komponententests sollten nur kleine Codeeinheiten testen, in der Regel Methoden, die idealerweise nur die zu testende Einheit ausführen, ohne einen anderen Code auszuführen (mit Ausnahme von privaten Methoden).

Ein Grund dafür ist, dass Komponententests so schnell wie möglich ausgeführt werden sollten, sodass Entwickler sie nach jeder kleinen Änderung am Code so oft wie möglich ausführen können. Sie möchten sofortiges Feedback von Komponententests erhalten. Selbst wenn das Laden des Spring-Kontextes normalerweise schnell ist und nur etwa eine Sekunde zur Ausführungszeit Ihres Tests hinzukommt, ist diese eine Sekunde ärgerlich, wenn Sie den Test einige hundert Mal pro Tag ausführen, wie es z Beispiel, umfangreiches Refactoring einer Klasse.

Ein weiterer Grund, sich an diese Regel zu halten, ist, dass Sie stark entkoppelte Klassen schreiben müssen. Wenn Sie keine Komponententests für eine Klasse schreiben können, die nur diese Klasse und sonst nichts trainiert, kann dies ein Zeichen dafür sein, dass Sie Ihr Klassendesign überdenken sollten.

Wenn Sie den gesamten Spring-Kontext für einen Test hochfahren, ist es nach dieser Definition kein Komponententest mehr, sondern ein Integrationstest, da Sie auch die gesamte Spring-Konfiguration, Bootstrapping, Autowiring usw. testen. e. die Integration Ihrer Klassen in eine Spring-Anwendung.

1

@SpringRunner sollte verwendet werden, wenn Ihre Klasse irgendwelche Abhängigkeiten von Beans verwendet, wenn Sie eine unabhängige Klasse ohne Abhängigkeiten des Anwendungskontextes verwenden, sollten Sie besser @SpringRunner nicht verwenden. Wenn ich Ihnen Klasse ‚RewardDurationCalculator‘ sehen es verwendet keine Abhängigkeiten, sollte es nicht @SpringRunner verwenden und auch für in der Tat Mocks ...

Weiterführende Literatur:

  1. https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/test/context/junit4/SpringRunner.html
+0

Es hat eine Abhängigkeit. Es ist Uhr, die verspottet werden kann. Aber ich habe deine Idee, danke. – SoulCub

Verwandte Themen