AnyString()作为单元测试的参数

时间:2016-09-09 19:27:14

标签: java junit mockito powermock assertj

我必须处理没有测试的遗留应用程序。所以在我开始重构之前,我想确保一切正常。

现在想象以下情况:

public SomeObject doSomething(final OtherObject x, final String something) {
    if(x == null) throw new RuntimeException("x may not be null!");
    ...
}

现在我想测试那个空检查,所以要确保它有效,一旦我重构我就不会失去它。

所以我做了这个

@Test(expected = RuntimeException.class)
public void ifOtherObjectIsNullExpectRuntimeException() {
    myTestObject.doSomething(null, "testString");
}

现在,这当然是有效的。

但不是" testString"我想传递一个随机字符串。

所以我尝试了:

@Test(expected = RuntimeException.class)
public void ifOtherObjectIsNullExpectRuntimeException() {
    myTestObject.doSomething(null, Mockito.anyString());
}

但这是不允许的,因为我得到

org.mockito.exceptions.misusing.InvalidUseOfMatchersException: ...您不能在验证或存根之外使用参数匹配器

我确实理解了这一点的含义,但我想知道如果不参数化我的测试之类的话,我是否仍能设法做我想做的事情。 我可以使用的唯一库是Junit,AssertJ,Mockito和Powermock。

有什么想法吗?

4 个答案:

答案 0 :(得分:3)

测试应该是确定性的。在测试失败时,在测试中使用随机值会很难重现行为。我建议您为测试创建一个>> combination(combination(:,1) == 1,:) = []; >> combination(combination(:,3) == 4,:) = []; 常量,例如foreach (Uri imageUri in uriList) { BitmapImage bmi = new BitmapImage(new Uri(imageUri)); Image image = new Image(); image.source = bmi; flipView.Items.Add(image); }

答案 1 :(得分:2)

好吧,就像Mockito试图通过该异常告诉你的那样,你并不是真的如何使用anyString。这些方法只能由模拟使用。

那么,为什么不尝试使用实际的随机字符串进行测试?在这种情况下我个人最喜欢的是:java.util.UUID.randomUUID() .toString()。这实际上总会生成一个从未用于您的测试的全新字符串。

我还想补充一点,如果您正在为SomeObject课程编写测试,那么您应该避免模仿SomeObject的行为。从你的例子来看,你并没有完全这样做,但看起来你可能会走这条路。模拟您尝试测试的实现的依赖关系,而不是实现本身!这是非常重要的;否则你实际上没有测试任何东西。

答案 2 :(得分:2)

你在这里混淆概念。

所有这些"嘲笑"在配置模拟对象时,应使用 anyString()之类的帮助程序。

但是当你检查你的测试代码时:

@Test(expected = RuntimeException.class)
public void ifOtherObjectIsNullExpectRuntimeException() {
  myTestObject.doSomething(null, "testString");
}

你会发现:这个测试绝对没有嘲弄。你只是无法在那个地方使用那些Mokito电话;因为"没有Mokito"在那个地方。

只是为了记录 - 无论如何都不需要过火。你的逻辑在这里很清楚:当第一个参数为null时,你抛出该异常。因此,作为第二个论点,它实际上并不重要。因此,想一个小时如何用任何第二个参数测试null是我的眼睛:浪费你的时间。

最后提示: java.lang.Objects 并且该类对null进行了很好的检查,因此我的生产代码看起来只有

public SomeObject doSomething(final OtherObject x, final String something) {
  Objects.requireNonNull(otherObject, "otherObject must not be null");
  Objects.requireNonNull(something, "something must not be null");

只有区别:要求...抛出NullPointerExceptions

最后终于:有人建议对每个参数进行最终决定;但我不会这样做。它在99%的案例中增加了 no 值。它只是意味着您有更多的代码可供阅读;没有充分的理由。但这是一个风格问题。

编辑关于进行测试以检查未来潜在变化的评论:您不应该这样做:

  1. 在某种程度上,验证输入的方式是一个实现细节。您没有测试实施细节。换句话说:
  2. 你的方法有一定的契约(你可以通过编写一个javadoc非正式地指定"在空输入上抛出NPE")。您的测试应验证完全当前合同。合同是:如果第一个参数为null则抛出。
  3. 也许是另一种观点;因为我仍然认为你在这里浪费你的时间!您应确保所有界面都清晰,易于理解且易于使用。它们允许您的代码用户轻松地做正确的事情;并防止他做错事。这就是你应该关注的 - 整个界面的质量! 因此,不要担心如何为潜在的未来变化编写测试;只需确保您的代码库完全一致。

答案 3 :(得分:1)

我对mockito知之甚少,但你总能创建自己的随机字符串生成器。也许这可以工作,你可以在其中修改更多类型的输入