当前位置: 首页 > 知识库问答 >
问题:

Mockito:验证模拟(使用“RETURNS_DEEP_STUBS”)返回的电话比预期的多

乐正乐湛
2023-03-14

查看下面的代码,我只期望对getSand()的调用发生一次,但测试失败并对其进行了四次调用。这些调用发生在哪里?我想编写一个测试以确保只对getSand()进行了一次调用。

来源

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class DeepSandTest {

    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
    SandBox mockSandBox;

    @Test
    public void should(){
        when(mockSandBox.getSand().doA()).thenReturn(1);
        when(mockSandBox.getSand().doB()).thenReturn(1);
        when(mockSandBox.getSand().doC()).thenReturn(1);

        DeepSand deepSand = new DeepSand(mockSandBox);
        deepSand.getTipple();

        verify(mockSandBox, times(1)).getSand();
    }

    public class DeepSand{

        private SandBox sandBox;

        public DeepSand(SandBox sandBox) {
            this.sandBox = sandBox;
        }

        public void getTipple(){
            Sand sand = sandBox.getSand();
            sand.doA();
            sand.doB();
            sand.doC();
        }
    }

    public interface SandBox{
        public Sand getSand();
    }

    public interface Sand{
        public Integer doA();
        public Integer doB();
        public Integer doC();
    }
}

输出

org.mockito.exceptions.verification.TooManyActualInvocations: 
mockSandBox.getSand();
Wanted 1 time:
-> at DeepSandTest.should(DeepSandTest.java:26)
But was 4 times. Undesired invocation:
-> at DeepSandTest.should(DeepSandTest.java:20)

详细信息Java1.6, JUnit 4.11, Mockito 1.9.5

如果您将深度存根视为模拟对象树,那么您应该只验证叶子(“链中的最后一个模拟”),因为节点包含在设置叶子行为所需的调用链中。换句话说,节点在叶子的设置过程中被调用。

共有3个答案

井高峯
2023-03-14

来自文档:“验证API不支持‘链接’,所以深存根不会改变您进行验证的方式。”

来源:http://mockito.googlecode.com/svn/tags/1.8.3/javadoc/org/mockito/Mockito.html#RETURNS_DEEP_STUBS

墨翔宇
2023-03-14

来自答案文档。返回\u DEEP\u存根:

Please see the {@link org.mockito.Mockito#RETURNS_DEEP_STUBS} documentation for more details.

来自Mockito。返回\u DEEP\u存根:

Verification only works with the last mock in the chain. You can use verification modes. 
[...]
when(person.getAddress(anyString()).getStreet().getName()).thenReturn("deep");
[...]
inOrder.verify(person.getAddress("the docks").getStreet(), times(1)).getName();

因此,我认为,为了让验证工作正常进行,必须将模拟重写为以下内容:

@Mock
SandBox mockSandBox;

@Mock
Sand mockSand;

@Test
public void should()
{
    when( mockSand.doA() ).thenReturn( 1 );
    when( mockSand.doB() ).thenReturn( 1 );
    when( mockSand.doC() ).thenReturn( 1 );

    when( mockSandBox.getSand() ).thenReturn( mockSand );

    DeepSand deepSand = new DeepSand( mockSandBox );
    deepSand.getTipple();

    verify( mockSandBox, times( 1 ) ).getSand();
}

或者只验证doA、doB和doC的调用,而不验证getSand()的调用这取决于你想在这里测试什么。

邹京
2023-03-14

由于验证API中不支持deeps存根,因此它将您的设置计算为调用,并在第二次调用时进行投诉,即:

when(mockSandBox.getSand().doB()).thenReturn(1);

我会跳过使用RETURNS\u DEEP\u存根,只使用另一个模拟:

...
@Mock
SandBox mockSandBox;

@Mock
Sand sand;

@Test
public void should(){
    when(mockSandBox.getSand()).thenReturn(sand);
    when(sand.doA()).thenReturn(1);
    when(sand.doB()).thenReturn(1);
    when(sand.doC()).thenReturn(1);
...
 类似资料:
  • 我正在使用JUnit和Mockito库来测试我的应用程序。问题是,当我在代码下面执行时,值在运行时没有返回空列表,并且测试失败。理想情况下,当get执行时,它应该返回空列表 我热切期待着支持。有没有人能帮我一下,如何通过这个测试用例???。如何通过Mockito使第8行的控件通过测试用例??? 请假设,下面两个类没有真实的代码,我们只有二进制文件作为JAR文件,我们不能修改下面的代码....我附上

  • 我正在尝试测试另一个方法使用的getCookieByName方法。但是,我不确定我是否正确执行了此操作,因为该方法似乎被多次调用,并且它在第一次尝试时设置了值,但在最后一次调用时为空。我认为模拟调用的顺序可能是错误的,或者其中一些可能不需要,但是如果我删除了其中任何一个,我仍然会得到其他错误,因此不确定我到底做错了什么。 这是我的测试和模拟调用,以及在同一个方法中两次调用getCookieByNa

  • 我正在使用HTML5表单验证来验证来自印度的电话号码。 null null 建议一个模式,可以检测有效的印度电话号码。 到目前为止,我的模式是,但它不检查第一个数字是7、8还是9。

  • 我正在处理一个Spring Boot java服务,该服务包含一个Camel处理器类,如下所示: 当我运行它时,我得到一个失败,声明对1*LogService.Update(_)的调用太少(0个调用)。我试着调试代码,在MyProc中,语句被命中,并且logService对象在高亮显示时(在Eclipse中)状态为“mock for type logService named$spock_shar

  • 我正在尝试对Angular 5进行自定义验证,但我面临以下错误 如果值不符合要求,我只想向表单返回一个错误,这是我的代码: 这是我的表单所在的组件 此代码位于包含我要实现的验证的文件中: 这种验证只适用于可观察到的情况吗?或者我可以在没有promise或可观察的情况下进行验证吗?