测试API,它使用JUnit返回多个值

时间:2011-06-05 13:32:55

标签: java unit-testing junit

我想测试一个API,它接收一个参数并返回一个集合。该测试使用参数调用API,并检查返回的集合是否包含预期值。

假设,我必须使用参数arg1arg2arg3测试API并检查值ab,{{1出现在返回的集合中。也就是说,我的测试用例如下:

  • 使用c调用API并检查是否arg1ab出现在返回的集合中。
  • 使用c调用API并检查是否arg2ab出现在返回的集合中。
  • 使用c调用API并检查是否arg3ab出现在返回的集合中。

如何使用c开发此测试用例?如果我必须添加Junit 4怎么办?如果我必须检查返回的集合中是否出现值arg4,该怎么办?我可以从配置中读取参数列表和期望值吗?

4 个答案:

答案 0 :(得分:4)

流利断言

首先,使用FEST-Assertions库引入带有意义错误消息的令人愉快的断言:

assertThat(method(arg1)).containsExactly(a, b, c);
assertThat(method(arg2)).containsExactly(a, b, c);
assertThat(method(arg3)).containsExactly(a, b, c);

BDD方式

但我理解你的问题不是关于语法,而是关于方法论:如果arg4需要测试,你该怎么办?好吧,如果arg1arg4具有不同的语义含义,我建议你对每个参数进行单独的测试。 非常详细,但也非常易读(伪代码):

@Test
public void shouldReturnAbcWhenSomeArgumentUsed() {
  //given
  Object arg = arg1;

  //when
  Set<Object> result = method(arg);

  //then
  assertThat(result).containsExactly(a, b, c);
}

..并为每次测试重复此操作。关键部分是:方法名称应该代表参数的含义,这个方法实际测试的是什么,你期望什么,场景是什么?

考虑测试isEven方法。我建议进行以下测试:

  • shouldReturnTrueForZero
  • shouldReturnTrueForSmallPositiveEvenNumber
  • shouldReturnTrueForLargePositiveEvenNumber
  • shouldReturnFalseForSmallPositiveOddNumber
  • shouldReturnFalseForLargePositiveOddNumber
  • ...并反映负数的测试

每个测试代表一个略有不同,定义明确的场景。另一方面,你可能会产生数千个shouldReturnFalseWhen227,但是这个测试套件的价值是多少,除了它很大?测试语义上不同的参数和极端情况,准确定义正在测试的情况。

参数化方式

如果你真的想要只有一个通用的测试方法,那么Parameterized跑步者就是你的选择。我认为这个例子是不言自明的。注意:您也可以参数化预期值。

@RunWith(value = Parameterized.class)
public class JunitTest6 {

    private Object arg;

    public JunitTest6(Object arg) {
        this.arg = arg;
    }

    @Parameterized.Parameters
    public static Collection<Object[]> data() {
        return Arrays.asList(
                new Object[][]{
                        {arg1},
                        {arg2},
                        {arg3}
                });
    }

    @Test
    public void testMethod() {
        assertThat(method(arg)).containsExcatly(a, b, c);
    }

}

基于this

答案 1 :(得分:3)

我通常会转向Hamcrest这样的事情 - 它是一个用于声明性地编写“matchers”的库,它与JUnit非常相似。

但是,this question on SO指出尽管可以使用Hamcrest完成,但更简单的方法是使用java.util.Collection中的containsAll方法:

ArrayList<Integer> expected = new ArrayList<Integer>();
expected.add(1); expected.add(2); expected.add(3);

assertTrue(actual.containsAll(expected));

答案 2 :(得分:3)

就方法而言:

“敏捷”方式

测试需要持续的开发和重构,就像生产代码一样。同样,YAGNI(“你不需要它”)等原则也适用。如果现在 ,您只需要测试abc,那么我将从普通的硬编码单元测试开始。如果以后你的测试用例开始变得重复,那么一定要考虑如何重构它们。

或许你现在已经处于这一点,但对我而言,这个问题似乎没有提供足够的信息来提供有关如何重构单元测试的更具体的建议。从XML读取测试?生成组合测试数据?参数化的跑步者(根据@Tomasz)?也许我只是没有充分理解这个问题,但所述的问题似乎仍然过于抽象。

答案 3 :(得分:1)

假设您要测试带有一个参数并返回一个集合的方法“method1”:

Set result = method1(arg1);
assertTrue(result.contains(a));
assertTrue(result.contains(b));
assertTrue(result.contains(c));

但也许最好的方法是将该组直接与预期值进行比较:

Set expected = new HashSet();
expected.add(a);
expected.add(b);
expected.add(c);

assertEquals(expected, method1(arg1));
assertEquals(expected, method1(arg2));
assertEquals(expected, method1(arg3));

当然,如果需要,不要使用循环来更通用。