首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Mockito期望参数不匹配

Mockito期望参数不匹配
EN

Stack Overflow用户
提问于 2022-06-04 13:42:35
回答 1查看 285关注 0票数 1

我正在用JUnit 4和Mockito4.6.1编写一个单元测试。我在模拟一个具有特定输入值的接口方法。当传递不同的值时,我预期会出现参数不匹配错误,但不会抛出。

请考虑以下示例:

代码语言:javascript
运行
复制
public class SomeTest {
    @Test
    public void test() {
        SomeInterface mock = Mockito.mock(SomeInterface.class, Mockito.withSettings().strictness(Strictness.STRICT_STUBS));

        // Only mock test(true) and not test(false).
        Mockito.when(mock.test(true)).thenReturn(1);

        Assert.assertEquals(mock.test(true), 1);
        
        Assert.assertEquals(
                // Expecting argument mismatch error
                mock.test(false), 
                2
        );
    }

    interface SomeInterface {
        int test(Boolean arg);
    }
}

我在嘲笑SomeInterface.test(true)返回1,这和预期的一样。现在,当我调用mock.test(false)时,我期望参数不匹配,因为它不是在模拟设置中定义的,并且启用了严格模式。相反,它返回0,就好像它被模仿了一样。

我是不是漏掉了导致这一切发生的东西?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-06-05 01:16:15

问题1.我们必须启用存根进行测试。

STRICT_STUBS -确保干净的测试,减少测试代码的重复,提高调试能力。灵活性和生产力的最佳结合。强烈推荐。计划默认为Mockito v4。通过MockitoRule、MockitoJUnitRunner或MockitoSession启用它。详细信息请参见STRICT_STUBS。

根据文档,它可以通过MockitoJUnitRunner.StrictStubs.class完成

代码语言:javascript
运行
复制
@RunWith(MockitoJUnitRunner.StrictStubs.class)

严格性规则

代码语言:javascript
运行
复制
@Rule public MockitoRule rule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);

问题2.当模拟定义和模拟调用在一个源类中执行时,参数严格性不起作用。

根据Mockito 源代码

如果固执和调用位于同一个源文件中,我们假设它们在测试代码中,并且我们不会将其标记为不匹配:

摘要。工作测试将是:

代码语言:javascript
运行
复制
import org.junit.Assert;
import org.junit.Test;

import org.junit.runner.RunWith;
import org.mockito.Mockito;

import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.quality.Strictness;

import static org.mockito.Mockito.*;

@RunWith(MockitoJUnitRunner.StrictStubs.class)
public class SomeTest {
    @Test
    public void test() {
        SomeInterface mock = Mockito.mock(SomeInterface.class, withSettings().strictness(Strictness.STRICT_STUBS));
        Mockito.when(mock.test(true)).thenReturn(1);

        SomeInterfaceImpl someInterface = new SomeInterfaceImpl(mock);

        Assert.assertEquals(someInterface.test(), 2);
    }
}

public interface SomeInterface {
    int test(Boolean arg);
}

public class SomeInterfaceImpl {
    private SomeInterface someInterface;
    public SomeInterfaceImpl(SomeInterface someInterface) {
        this.someInterface = someInterface;
    }

    public int test() {
        return someInterface.test(false);
    }
}

在执行死刑时我们得到:

代码语言:javascript
运行
复制
org.mockito.exceptions.misusing.PotentialStubbingProblem: 
Strict stubbing argument mismatch. Please check:
 - this invocation of 'test' method:
    someInterface.test(false);
    -> at com.example.SomeInterfaceImpl.test(SomeInterfaceImpl.java:10)
 - has following stubbing(s) with different arguments:
    1. someInterface.test(true);
      -> at com.example.SomeTest.test(SomeTest.java:26)
Typically, stubbing argument mismatch indicates user mistake when writing tests.
Mockito fails early so that you can debug potential problem easily.
However, there are legit scenarios when this exception generates false negative signal:
  - stubbing the same method multiple times using 'given().will()' or 'when().then()' API
    Please use 'will().given()' or 'doReturn().when()' API for stubbing.
  - stubbed method is intentionally invoked with different arguments by code under test
    Please use default or 'silent' JUnit Rule (equivalent of Strictness.LENIENT).
For more information see javadoc for PotentialStubbingProblem class.

更可取的解决方案

您可以使用IllegalArgumentException为模拟定义默认答案,以防使用不匹配参数执行模拟。此解决方案将始终在没有源文件限制的情况下工作。

代码语言:javascript
运行
复制
import org.junit.Assert;
import org.junit.Test;

import org.junit.runner.RunWith;
import org.mockito.Mockito;

import org.mockito.junit.MockitoJUnitRunner;

import static org.mockito.Mockito.doReturn;

@RunWith(MockitoJUnitRunner.class)
public class SomeTest {
    @Test
    public void test() {
        SomeInterface mock = Mockito.mock(SomeInterface.class, Mockito.withSettings().defaultAnswer(
                invocation -> {
                    throw new IllegalArgumentException(String.format("You cannot invoke %s with %s", invocation.getMethod(), java.util.Arrays.toString(invocation.getArguments())));
                }
        ));

        // Only mock test(true) and not test(false).
        doReturn(1).when(mock).test(true);

        Assert.assertEquals(mock.test(true), 1);

        Assert.assertEquals(
                // Expecting argument mismatch error
                mock.test(false),
                2
        );
    }
}

在执行死刑时我们得到:

代码语言:javascript
运行
复制
java.lang.IllegalArgumentException: You cannot invoke public abstract int com.example.SomeInterface.test(java.lang.Boolean) with [false]
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72500235

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档