Java 有没有办法在单个@test中测试一组输入和一组输出?

Java 有没有办法在单个@test中测试一组输入和一组输出?,java,unit-testing,mockito,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");

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

  @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 */);
  }

您需要的是一个参数化测试。 其思想是定义一个通用方法,在该方法中定义一组输入和一组预期输入

但是Mockito在这里没有帮助,因为运行/执行测试不是模拟库的工作。 我最喜欢的单元测试库是JUnit,它将很好地解决这个问题

例如,使用old way,您可以编写如下内容:

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),
    );
}

您需要的是一个参数化测试。 其思想是定义一个通用方法,在该方法中定义一组输入和一组预期输入

但是Mockito在这里没有帮助,因为运行/执行测试不是模拟库的工作。 我最喜欢的单元测试库是JUnit,它将很好地解决这个问题

例如,使用old way,您可以编写如下内容:

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),
    );
}

需要参数化测试,但在OP示例中,也需要类似Mockito的模拟库,因为参数化的是协作者的行为,而不是SUT的输入。@Kevin Welker我完全同意。我提到了测试执行。我更新为更具体一点。在两个示例中,我认为您都有参数类型reversed@Kevin韦尔克:你说得对。在没有IDE的情况下编写代码有时有点容易出错。我纠正了。感谢您:需要参数化测试,但在OP示例中,也需要像Mockito这样的模拟库,因为参数化的是协作者的行为,而不是SUT的输入。@Kevin Welker我完全同意。我提到了测试执行。我更新为更具体一点。在两个示例中,我认为您都有参数类型reversed@Kevin韦尔克:你说得对。在没有IDE的情况下编写代码有时有点容易出错。我纠正了。多谢各位: