2017-10-13 15 views
0

私は同僚とこのアプローチについて主張しています。彼らは、SpringRunnerを統合レベルまたは機能レベルでのみ使用すると言います。ユニットテストでSpringRunnerを使用することはできますか?

質問は、以下のレベルでそれを使用するとどのような長所と短所ですか?例えば

私はシンプルな豆持っている:

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(); 
    } 

} 

いくつかの計算ロジックを行っています。そのために私はまた、コンフィグ春います

@Configuration 
public class RewardDurationCalculatorConfiguration { 

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

} 

は、なぜ私はこのようにそれのためのユニットテストを書くことはできません。

@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()); 
    } 

} 

私は、このようなアプローチを使用して直面することができますどのような短所?

答えて

4

私はあなたの同僚に同意する傾向があります。

単体テストは、他のコード(プライベートメソッドを除く)を実行することなく、単体テストのみを理想的に実行する小さなコード単位、通常はメソッドをテストする必要があります。

単体テストはできるだけ速く実行する必要があります。そのため、開発者はできるだけ頻繁にコードを実行します。単体テストから即座にフィードバックを得たいと思っています。 Springコンテキストの読み込みが通常は静かで、テストの実行時間に約1秒足らずであっても、テストを1日に数百回実行すると、この1秒は迷惑になる例えば、クラスの大規模なリファクタリング。

このルールに従うもう1つの理由は、分離されたクラスを作成する必要があるということです。そのクラスだけを実行するクラスの単体テストを書くことができない場合、それはあなたのクラス設計を再考するべきであるという兆候です。

この定義では、テストのためにSpringコンテキスト全体を立ち上げると、これは単体テストではなく、統合テストです。これはSpringの設定全体、ブートストラップ、autowiringなどもテストしています。 e。クラスのSpringアプリケーションへの統合

1

@SpringRunnerは、クラスが任意のBean依存関係を使用している場合に使用します。クラスが独立していて、アプリケーションコンテキストの依存関係がなく、@SpringRunnerを使用しない方がよい場合。さらに読書のために...

を私はあなたのクラスのRewardDurationCalculator」を参照している場合、それはすべての依存関係を使用していない、それは@SpringRunnerを使用してはならないとさえモック実際の問題のために:

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

1つの依存関係があります。それは嘲笑できる時計です。しかし、私はあなたのアイデアを、ありがとう。 – SoulCub

関連する問題