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

Mockito:使用"thenBack"中的方法返回模拟不起作用

孔逸春
2023-03-14

我遇到了Mockito的一个bug,但我想知道是否有其他人可以解释为什么这个测试不起作用。

基本上,我有两个对象,如下所示:

public class FirstObject {
    private SecondObject secondObject;
    public SecondObject getSecondObject() { return secondObject; }
}

public class SecondObject {
    private String name;
    public String getName() { return name; }
}

第一个对象是通过注释和之前的方法模拟的:

@Mock
FirstObject mockedFirstObject;

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

在方法中模拟第二个对象:

public SecondObject setupMockedSecondObject() {
    SecondObject secondObject = Mockito.mock(SecondObject.class);
    Mockito.when(secondObject.getName()).thenReturn("MockObject");
    return secondObject;
}

thenReturn包含对此方法的直接调用以设置并获取第二个对象的模拟时,它将失败:

@Test
public void notWorkingTest() {
    Mockito.when(mockedFirstObject.getSecondObject()).thenReturn(setupMockedSecondObject());
    Assert.assertEquals(mockedFirstObject.getSecondObject().getName(), "MockObject");
}

但是,当同一方法返回的模拟被分配给一个局部变量(在thenReturn中使用)时,它可以工作:

@Test
public void workingTest() {
    SecondObject mockedSecondObject = setupMockedSecondObject();
    Mockito.when(mockedFirstObject.getSecondObject()).thenReturn(mockedSecondObject);
    Assert.assertEquals(mockedFirstObject.getSecondObject().getName(), "MockObject");
}

我们是否做错了什么,或者这确实是Mockito中的一个缺陷/限制?有没有一个故意不起作用的原因?

共有3个答案

子车桐
2023-03-14
java prettyprint-override">@Test
public void testAuthenticate_ValidCredentials() throws FailedToAuthenticateException {

    String username = "User1";
    String password = "Password";
    /*Configure Returning True with when...thenReturn configuration on mock Object - Q5*/
   //Write your code here
    assertTrue(authenticator.authenticateUser(username, password));
}
鲍俊杰
2023-03-14

您不能在thenReturn使用方法,但您可以在thenAnswer中调用您的代码,这与基于thenReturn

因此你可以写:

@Test
public void nowWorkingTest() {
    Mockito.when(mockedFirstObject.getSecondObject()).thenAnswer(new Answer<Map>() {
        @Override
        public Map answer(InvocationOnMock invocation) {
            return setupMockedSecondObject();
        }
    });
    Assert.assertEquals(mockedFirstObject.getSecondObject().getName(), "MockObject");
}

让我们在这里找到另一个例子

太叔鹏云
2023-03-14

这确实是Mockito的一个局限性,在他们的FAQ中有提及:

不幸的是,您不能这样做:

when(m.foo()).thenReturn(mock(Foo.class));
//                         ^

原因是,如果我们允许上述结构,检测未完成的短截是行不通的。我们认为这是框架验证的“权衡”(另见以前的常见问题条目)。但是,您可以稍微更改代码,使其工作:

//extract local variable and start smiling:
Foo foo = mock(Foo.class);
when(m.foo()).thenReturn(foo);

如上所述,解决方法是将所需的返回值存储在局部变量中,就像您所做的那样。

我的理解是,每次调用它的方法时,Mockito都会验证它的用法。当在正在进行的存根过程中调用另一个方法时,您正在破坏其验证过程。

 类似资料:
  • 我有这门课(简体) 我试图模拟writeToFile方法,但没有成功 这个结果随着去到原来的方法,我也尝试了模拟具体的方法使用: 编辑:修复导入问题后,正如@pvpkiran所说,现在起作用了!我可以用DoAnswer来验证。

  • 我有以下几门课 我想为viewModel和UseCase编写一个ermetic测试: 但ViewModel.car似乎总是为空。在测试体中mockapi.fetchcar()检索提供的值,但在FetchCarUseCase中不检索。此外,如果我从界面中移除suspend关键字,那么嘲弄似乎可以很好地工作。 目前,由于一些其他条件,我无法使用Mockk库,所以我只能使用mockito。 我是不是漏掉

  • 问题内容: 使用模拟编写单元测试时遇到问题。我需要模拟的对象有很多吸气剂,我确实在代码中称呼它们。但是,这些不是我的单元测试的目的。因此,有一种方法可以模拟所有方法,而不是一个个地模拟它们。 这是代码示例: 这是我需要测试的服务等级 在测试类中,测试方法就像 因此,有一种方法可以避免将所有无用的“ field1”的“ when”写入“ field20” 问题答案: 您可以控制模拟的默认答案。在创建

  • 我在用Mock编写单元测试时遇到了一个问题。有一个对象,我需要模拟有很多getter,我在代码中调用它们。但是,这些不是我的单元测试的目的。所以,有没有一种方法我可以模拟所有的方法,而不是一个一个地模拟它们。 下面是代码示例: 那么,有没有一种方法可以避免为无用的“field1”到“field20”写所有的“when”

  • 问题内容: 我正在使用Mockito 1.9.5。我有以下代码: 我收到一句编译错误: 但是,当我使用模拟方法时,不会出现错误。谁能告诉我怎么回事?使用该方法时为什么会出现错误?当第三方提供且无法修改时,还有其他方法可以解决此问题吗? 问题答案: 编辑 :从Mockito 1.10.x开始,嵌入在类中的泛型类型现在由Mockito用于深层存根。即。 Mockito尽最大努力获取编译器嵌入的类型信息