java – Mockito风格anyXXX单元测试方法

前端之家收集整理的这篇文章主要介绍了java – Mockito风格anyXXX单元测试方法前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
当单元测试某些方法时,可能会出现一些情况,某些参数的值不重要,可以是任何值.

例如在这段代码中:

public void method(String arg1,String arg2,int arg3){
    if(arg1 == null) throw new NullPointerException("arg1 is null");

    //some other code
}

单元测试当arg1为null时的行为,则必须抛出NPE,其他参数的值不重要,它们可以是任何值或为空.

所以我想记录一个事实,即这些值对于被测试方法无关紧要.

我想到了以下选项:

选项1:定义ANY_XXX的常量

我想明确地创建常量ANY_STRING和ANY_INT,其中包含一个固定值,它记录它可以是任何值,并且被测方法不关心实际值.

我可以将所有这些常量放在一个名为Any的类中,并在所有测试类中重用它们.

选项2:ANY_XXX的随机

这个选项对我来说似乎有点黑客,因为我已经读过某个地方,随机性不应该被带入测试用例.但是在这种情况下,这个随机性将不可见,因为参数不会产生任何副作用.

哪种方法更适合更好,可读的测试?

更新:

虽然我可以通过在Any类中定义常量来使用ANY_XXX方法,但是我也在考虑用一些约束来生成ANY_XXX值,例如

Any.anyInteger().nonnegative();
Any.anyInteger().negative();

Any.anyString().thatStartsWith("ab");

我想,也许Hamcrest Matchers可以用来创建这个链接.但是我不知道这种做法是不是很好. anyObject()的类似方法已经由Mockito提供,但这些方法仅适用于Mocks和间谍,而不适用于普通对象.我想为普通对象实现相同的更多可读性测试.

为什么要这样做?

假设我有一个班

class MyObject{

     public MyObject(int param1,Object param2){
          if(param1 < 0) throw new IllegalArgumentException();
          if(param2 == null) throw new NullPointerException();
     }
}

而现在在编写测试构造函数

class MyObjectTest{

     @Test(expected=NullPointerException.class)
     public void testConstructor_ShouldThrowNullpointer_IfSecondParamIsNull(){

          //emphasizing the fact that value of first parameter has no relationship with result,for better test readability
          new MyObject(Any.anyInteger().nonnegative(),null);
     }
}

解决方法

我的偏好是建立一个实用程序类常量和方法,以帮助创建测试的常量值,例如:
public final class Values {
    public static final int ANY_INT = randomInt(Integer.MIN_VALUE,Integer.MAX_VALUE);
    public static final int ANY_POSITIVE_INT = randomInt(0,Integer.MAX_VALUE);
    public static final String ANY_ISBN = randomIsbn();
    // etc...

    public static int randomInt(int min,int max) { /* omitted */ }
    public static String randomIsbn() { /* omitted */ }

    // etc...
}

然后我将使用静态导入来拉取特定测试类所需的常量和方法.

我仅在不关心该值的情况下使用ANY_常量,我发现他们可以使测试的意图更清晰,例如:

// when
service.fooBar(ANY_INT,ANY_INT,5);

很明显,值5具有一定的意义 – 虽然它会更好地作为一个局部变量.

实用方法可用于在设置测试时自动生成值,例如:

// given
final String isbn1 = randomIsbn();
final String isbn2 = randomIsbn();
final Book[] books = { new Book(isbn1),new Book(isbn2) };

// when
bookRepository.store(books);

同样,这可以帮助测试课程关心测试本身,而不是关于数据设置.

除此之外,我也从域对象中使用了类似的方法.当您结合这两种方法时,可能会非常强大.例如.:

public final class Domain {
    public static Book book() {
        return new Book(randomIsbn());
    }
    // etc...
}

猜你在找的Java相关文章