我们正在与我的同事争论这种方法。他们说仅在集成或功能级别上使用 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();
}
}
也就是做一些计算逻辑。为此我还有 spring 配置:
@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());
}
}
使用这种方法我会面临哪些缺点?
我倾向于同意你同事的观点。
单元测试应该只测试小的代码单元,通常是单个类。他们应该只运行被测试的单元,而不执行该单元的依赖项中的任何代码。
原因之一是单元测试应该尽可能快地执行。在测试驱动开发 (TDD) 中,您通常希望能够在进行每一个小的更改后运行该套件,或者至少是其中的一个相关子集,以验证您没有破坏任何现有行为。仅当测试反馈是即时的时这才可行。如果您必须等待测试结果太长时间,您将减少运行它们的频率,这意味着反馈循环会变得更长。
在较小的 Spring 项目中,Spring 上下文加载速度非常快,因此您可能认为没有太大差异,但如果您经常运行测试,即使是短暂的延迟也会增加。在大型和较旧的代码库中,可能需要一段时间才能启动 Spring 上下文,并且在某些时候它会变得非常慢,以至于您不想每天多次运行整个测试套件,这会极大地损害您的能力练习 TDD。
坚持测试小代码单元的另一个方面是,它迫使您将代码构建为高度解耦(即可测试)的单元。如果您无法为仅测试该类而不测试其他类的类编写单元测试,则可能暗示有机会改进代码的设计。
总而言之,当您启动整个 Spring 上下文进行测试时,根据这个定义,它不再是单元测试,而是集成测试,因为您还在测试整个 Spring 配置、引导、自动装配等,即。 e.将您的类集成到 Spring 应用程序中。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)