有没有办法在单个@Test中测试一组输入与一组输出?

时间:2018-02-01 21:16:37

标签: java unit-testing mockito

有没有办法进行一系列类似的测试,比如

  @Test
  public void testA()  {
    when(foo.getVal()).thenReturn("A");
    response = myService.doThings(foo);
    assert(response.getCode() == 200);
  }

  @Test
  public void testB()  {
    when(foo.getVal()).thenReturn("B");
    response = myService.doThings(foo);
    assert(response.getCode() == 404);
  }

  @Test
  public void testC()  {
    when(foo.getVal()).thenReturn("C");
    response = myService.doThings(foo);
    assert(response.getCode() == 200);
  }

并执行类似(伪造的语法):

  @Test
  public void testABC()  {
    when(foo.getVal()).thenReturnEach("A", "B", "C");
    response = myService.doThings(foo);
    assertEach(/* somehow check a list of 200, 404, 200 */);
  }

1 个答案:

答案 0 :(得分:4)

您需要的是参数化测试。
我们的想法是定义一个"泛型"定义一组输入和一组预期的方法。

但Mockito不会在这里提供帮助,因为它不是模拟库运行/执行测试的工作 您最喜欢的单元测试库(我的是JUnit)将很好地解决它。

例如,使用JUnit 4 parameterized tests(旧方式),您可以编写以下内容:

import static org.junit.Assert.assertEquals;

import java.util.Arrays;
import java.util.Collection;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class MyServiceTest {

    @Parameters
    public static Collection<Object[]> data() {
        return Arrays.asList(new Object[][] {     
                 { "A", 200 }, { "B", 404 }, { "C", 200 } 
                 });
    }

    private int valInput;

    private String responseCodeOutput;

    private Foo foo = ...;

    public MyServiceTest(String valInput, int responseCodeOutput) {
        this.valInput = valInput;
        this.responseCodeOutput = responseCodeOutput;
    }

    @Test
    public void doThings() {     
        when(foo.getVal()).thenReturnEach(valInput);
        String response = myService.doThings(foo);
        Assert.assertEqual(responseCodeOutput, response);
    }
}

使用最近发布的JUnit 5,它仍然更清晰,更简单:

@ParameterizedTest
@MethodSource("doThingsProvider")
void doThings (String valInput, int expectedCode) {         
      when(foo.getVal()).thenReturnEach(valInput);
      String response = myService.doThings(foo);
      Assert.assertEqual(expectedCode, response);      
}

static Stream<Arguments> doThingsProvider() {
    return Stream.of(
        Arguments.of("A", 200),
        Arguments.of("B", 404),
        Arguments.of("C", 200),
    );
}