Mockito-Java8是一组Mockito附加组件,它们利用Java 8和lambda表达式使Mockito的模拟更加紧凑。
在2015年初,我进行了简短的演讲, Java 8为测试带来了力量! 我在GeeCON TDD 2015和DevConf.cz 2015上发表了演讲。在我使用4个示例的演讲中,我展示了Java 8(即lambda表达式)如何简化测试工具和总体上的测试。 这些工具之一就是Mokcito。 为了不让我的PoC代码死在幻灯片上并使之简单地供他人使用,我发布了一个小项目,其中有两个在特定情况下非常有用的Mockito Java 8附加组件。
快速介绍
作为前提,我们假设我们具有以下数据结构:
@Immutable
class ShipSearchCriteria {
int minimumRange;
int numberOfPhasers;
}
该库提供了两个附加组件:
Lambda匹配器 –允许在lambda表达式中定义匹配器逻辑。
given(ts.findNumberOfShipsInRangeByCriteria(
argLambda(sc -> sc.getMinimumRange() > 1000))).willReturn(4);
ArgumentCaptor – Java 8版本 –允许在一行中使用ArgumentCaptor
(此处与AssertJ一起使用):
verify(ts).findNumberOfShipsInRangeByCriteria(
assertArg(sc -> assertThat(sc.getMinimumRange()).isLessThan(2000)));
Lambda匹配器
借助静态方法argLambda
将创建一个lambda匹配器实例,该实例可用于在lambda表达式(此处用于存根)中定义匹配器逻辑。 当使用复杂的类作为参数传递时,它可能特别有用。
@Test
public void shouldAllowToUseLambdaInStubbing() {
//given
given(ts.findNumberOfShipsInRangeByCriteria(
argLambda(sc -> sc.getMinimumRange() > 1000))).willReturn(4);
//expect
assertThat(ts.findNumberOfShipsInRangeByCriteria(
new ShipSearchCriteria(1500, 2))).isEqualTo(4);
//expect
assertThat(ts.findNumberOfShipsInRangeByCriteria(
new ShipSearchCriteria(700, 2))).isEqualTo(0);
}
相比之下,使用Java 7中的自定义Answer实现的逻辑相同:
@Test
public void stubbingWithCustomAsnwerShouldBeLonger() { //old way
//given
given(ts.findNumberOfShipsInRangeByCriteria(any())).willAnswer(new Answer<Integer>() {
@Override
public Integer answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
ShipSearchCriteria criteria = (ShipSearchCriteria) args[0];
if (criteria.getMinimumRange() > 1000) {
return 4;
} else {
return 0;
}
}
});
//expect
assertThat(ts.findNumberOfShipsInRangeByCriteria(
new ShipSearchCriteria(1500, 2))).isEqualTo(4);
//expect
assertThat(ts.findNumberOfShipsInRangeByCriteria(
new ShipSearchCriteria(700, 2))).isEqualTo(0);
}
甚至Java 8和可读性较差的构造也无济于事:
@Test
public void stubbingWithCustomAsnwerShouldBeLongerEvenAsLambda() { //old way
//given
given(ts.findNumberOfShipsInRangeByCriteria(any())).willAnswer(invocation -> {
ShipSearchCriteria criteria = (ShipSearchCriteria) invocation.getArguments()[0];
return criteria.getMinimumRange() > 1000 ? 4 : 0;
});
//expect
assertThat(ts.findNumberOfShipsInRangeByCriteria(
new ShipSearchCriteria(1500, 2))).isEqualTo(4);
//expect
assertThat(ts.findNumberOfShipsInRangeByCriteria(
new ShipSearchCriteria(700, 2))).isEqualTo(0);
}
Argument Captor – Java 8版本
静态方法assertArg
创建一个参数匹配器,该实现器内部使用ArgumentMatcher
并在lambda表达式中提供一个断言。 下面的示例使用AssertJ提供有意义的错误消息,但是可以使用任何断言(例如来自TestNG或JUnit的本地声明)(如果确实需要)。 这允许内联ArgumentCaptor:
@Test
public void shouldAllowToUseAssertionInLambda() {
//when
ts.findNumberOfShipsInRangeByCriteria(searchCriteria);
//then
verify(ts).findNumberOfShipsInRangeByCriteria(
assertArg(sc -> assertThat(sc.getMinimumRange()).isLessThan(2000)));
}
与经典方式的3行相比:
@Test
public void shouldAllowToUseArgumentCaptorInClassicWay() { //old way
//when
ts.findNumberOfShipsInRangeByCriteria(searchCriteria);
//then
ArgumentCaptor<ShipSearchCriteria> captor =
ArgumentCaptor.forClass(ShipSearchCriteria.class);
verify(ts).findNumberOfShipsInRangeByCriteria(captor.capture());
assertThat(captor.getValue().getMinimumRange()).isLessThan(2000);
}
摘要
所呈现的附加组件是作为我的会议演讲的PoC创建的,但是应具有完全的功能,并在特定情况下可能有用。 要在您的项目中使用它,只需使用Mockito 1.10.x或2.0.x-beta,将mockito-java8
添加为依赖项,当然可以使用Java 8+编译您的项目。
- 可在项目网页上找到更多详细信息: https : //github.com/szpak/mockito-java8