使用Mockitos传递参数化输入

l7wslrjt  于 2022-11-08  发布在  其他
关注(0)|答案(4)|浏览(208)

我正在使用Mockito进行单元测试。我想知道是否可以像在Junit测试中那样发送参数化的输入参数
例如:

@InjectMocks
MockClass mockClass = new MockClass();

@Test
public void mockTestMethod()
    {
    mockClass.testMethod(stringInput); 
// here I want to pass a list of String inputs 
// this is possible in Junit through Parameterized.class.. 
// wondering if its can be done in Mockito
    }
gab6jxml

gab6jxml1#

在JUnit中,Parameterized tests使用a special runner来确保测试被多次示例化,因此每个测试方法被多次调用。Mockito是一个用于编写特定单元测试的工具,因此没有内置的功能来多次运行具有不同Mockito期望的相同测试。
如果要更改测试条件,最好执行以下操作之一:

  • 使用JUnit参数化您的测试,为您想要的模拟输入提供一个参数;
  • 在测试中运行一个不同参数的循环,不幸的是,这避免了“每个方法测试一个东西”的原则
  • 提取一个实际执行测试的方法,并为每个需要的mock创建一个新的@Test方法。

请注意,没有禁止使用mock对象作为@Parameterized测试参数。如果您希望基于mock进行参数化,您可以这样做,可能创建mock并在测试的静态方法中设置期望值。

关于跑步者的注意事项:此Parameterized test runner与Mockito的MockitoJUnitRunner冲突:每个测试类只能有一个runner。如果同时使用@Before和@After方法或a Mockito JUnit4 rule方法,您将需要切换到这两种方法。

例如,从a different answer压缩,详细说明了参数化runner与JUnit规则,以及从JUnit4 Parameterized Test文档页面与MockitoRule文档页面进行提升:

@RunWith(Parameterized.class)
public class YourComponentTest {
    @Rule public MockitoRule rule = MockitoJUnit.rule();
    @Mock YourDep mockYourDep;

    @Parameters public static Collection<Object[]> data() { /* Return the values */ }

    public YourComponentTest(Parameter parameter) { /* Save the parameter to a field */ }

    @Test public void test() { /* Use the field value in assertions */ }
}
b5lpy0ml

b5lpy0ml2#

如果您一直使用旧版本的mockito,其中MockitoRule不可用,另一种可能性是使用MockitoAnnotations.initMocks显式初始化mock:

@RunWith(Parameterized.class)
public class YourComponentTest {        
    @Mock YourDep mockYourDep;

    @Parameter
    public Parameter parameter;

    @Parameters public static Collection<Object[]> data() { /* Return the values */ }

    @Before
    public void init() {
        MockitoAnnotations.initMocks(this);
    }

    @Test public void test() { /* Use the field value in assertions */ }
}
vlurs2pr

vlurs2pr3#

您可以使用JUnitParamsRunner。下面是我的操作方法:

import junitparams.JUnitParamsRunner;
import junitparams.Parameters;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;

import java.util.Arrays;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;

@RunWith(value = JUnitParamsRunner.class)
public class ParameterizedMockitoTest {

    @InjectMocks
    private SomeService someService;
    @Mock
    private SomeOtherService someOtherService;

    @Before
    public void setup() {
        initMocks(this);
    }

    @Test
    @Parameters(method = "getParameters")
    public void testWithParameters(Boolean parameter, Boolean expected) throws Exception {
        when(someOtherService.getSomething()).thenReturn(new Something());
        Boolean testObject = someService.getTestObject(parameter);
        assertThat(testObject, is(expected));
    }

    @Test
    public void testSomeBasicStuffWithoutParameters() {
        int i = 0;
        assertThat(i, is(0));
    }

    public Iterable getParameters() {
        return Arrays.asList(new Object[][]{
                {Boolean.TRUE, Boolean.TRUE},
                {Boolean.FALSE, Boolean.FALSE},
        });
    }
}
xqnpmsa8

xqnpmsa84#

解决这个问题的方法是:

  1. @ExtendWith(MockitoExtension.class)的类别层级注解
    1.使用@Mock注解每个模拟对象
  2. @InjectMocks。或者一个用@BeforeEach注解的setup方法,在这里你初始化了要测试的类。
    1.如果您需要@test注解,请确保您导入了org.junit.jupiter.api.Testorg.junit.test将不起作用!
    我用的是mockito第4版。

相关问题