【问题标题】:passing Parameterized input using Mockitos使用 Mockitos 传递参数化输入
【发布时间】:2012-09-26 16:20:23
【问题描述】:

我正在使用 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
    } 

【问题讨论】:

  • 你能提供一个例子来说明你想如何在你的单元测试中使用 Mockito 吗?

标签: java unit-testing mockito


【解决方案1】:

在 JUnit 中,Parameterized tests 使用 a special runner 确保测试被多次实例化,因此每个测试方法都被多次调用。 Mockito 是一种用于编写特定单元测试的工具,因此没有内置功能可以以不同的 Mockito 期望多次运行相同的测试。

如果您希望更改测试条件,最好的办法是执行以下操作之一:

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

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


关于跑步者的注意事项:这个Parameterized test runner 与 Mockito 的MockitoJUnitRunner 冲突:每个测试类只能有一个跑步者。如果您同时使用它们,您需要切换到 @Before and @After methodsa Mockito JUnit4 rule 进行设置。

作为一个例子,压缩自 a different answer,它解释了更多关于参数化运行器与 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 */ }
}

【讨论】:

  • 我确信这是最终的答案。但是您是否愿意评论 (stackoverflow.com/questions/27745691/…) 将@RunWith(Parameterized.class) 与另一个@RunWith 组合的可能性。我试图了解如何将这种技术与@RunWith(MockitoJUnitRunner.class) 一起使用,但它超出了我的范围(请参阅我的 cmets 那里)。鉴于你所说的,我有疑问,但我想我会问......
  • @mike 是的,您可以使用该技术创建一个参数化的 Mockito 运行器,但是虽然该帖子对于类加载器操作运行器或使用动态测试的运行器可能特别有用,但在几乎所有情况下这纯粹是矫枉过正Mockito 情况,因为 @Rule 会以更现代的惯用方式实现这一点。 (MockitoJUnitRunner 早于 JUnit 规则。)如果您想了解如何组合它们,最好在另一个问题中解决 - 它不适合评论框,也不是对任何一个问题的一般回答。
  • 谢谢。您的意思是开始一个新问题来询问使用@Rule 的明确示例?我现在已经这样做了:stackoverflow.com/questions/40793464/…。希望你有时间......
【解决方案2】:

如果您被旧版本的 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 */ }
}

【讨论】:

    【解决方案3】:

    您可以使用 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},
            });
        }
    }
    

    【讨论】:

    • 只有一个音符。此 getParameters 方法不必是公共方法。
    • 正确,并且使用junit5,奶头方法不必再公开了。
    猜你喜欢
    • 2015-12-09
    • 2023-02-07
    • 2014-01-22
    • 2011-10-18
    • 1970-01-01
    • 2016-05-06
    • 2021-10-06
    • 2017-11-16
    相关资源
    最近更新 更多