Java 模拟对象和真实对象给出不同的结果

Java 模拟对象和真实对象给出不同的结果,java,junit,mocking,mockito,Java,Junit,Mocking,Mockito,我已经开始学习JUNIT了。 以下是我正在努力实现的目标。 我有一个类来检查inputString是否是secretKey的一部分 public class StringChecker { public boolean isEqual(String name) { boolean isEqual = false; if(getSecretKey().contains(name)) { isEqual = true; } return

我已经开始学习JUNIT了。 以下是我正在努力实现的目标。 我有一个类来检查inputString是否是secretKey的一部分

public class StringChecker {


public boolean isEqual(String name)
{
    boolean isEqual = false;
    if(getSecretKey().contains(name))
    {
        isEqual = true;
    }

    return isEqual;
}

public String getSecretKey()
{
    return "OSKAR";
}

}
我的测试班是这个

公共类随机检查{
@试验
公共空间相等()
{
StringChecker-StringChecker=mock(StringChecker.class);
当(stringChecker.getSecretKey())。然后返回(“james”);

//assertEquals(true,new StringChecker().isEqual(“OSKAR”));mockito mock是一个具有被模拟类接口的对象,但不是其实现。您的
StringChecker
被模拟,这意味着没有实现代码像您假设的那样从
isEqual
调用
getSecretKey

您可以使用mockito
spy
,请参阅:

Mockito.spy()是一种推荐的创建部分mock的方法。原因是它保证对正确构造的对象调用真正的方法,因为您负责构造传递给spy()方法的对象


mockito mock是一个具有mock类接口的对象,但不是它的实现。您的
StringChecker
被mock,这意味着没有实现代码像您假设的那样从
isEqual
调用
getSecretKey

您可以使用mockito
spy
,请参阅:

Mockito.spy()是一种推荐的创建部分mock的方法。原因是它保证对正确构造的对象调用真正的方法,因为您负责构造传递给spy()方法的对象


新手失误

这是我犯的一个新秀错误(被提及)。
我模拟了StringChecker类,但没有为isEqual(String)方法提供任何实现 因为没有实现,所以我得到了默认值。在本例中,false(方法的返回类型是boolean)

解决方案

使用静态方法spy()。@Arnold再次提及。
下面是我的工作代码

@Test
public void isEqualTest()
{
    StringChecker stringChecker = new StringChecker();

    StringChecker spy = spy(stringChecker);

    when(spy.getSecretKey()).thenReturn("james");  // providing implementation for the method

    assertEquals(true, spy.isEqual("james"));

}
我从中学到了什么

如果您打算使用模拟对象的方法(简单地说,为模拟对象的方法提供实现),那么仅仅通过模拟对象并不能完成任务

小费

如果要查看模拟对象返回的默认值,只需在sysout中调用模拟对象的方法(不提供实现)。

希望它能帮助像我这样的人。和平

新手错误

这是我犯的一个新秀错误(被提及)。
我模拟了StringChecker类,但没有为
isEqual(String)方法提供任何实现 因为没有实现,所以我得到了默认值。在本例中,false(方法的返回类型是boolean)

解决方案

使用静态方法spy()。@Arnold再次提及。
下面是我的工作代码

@Test
public void isEqualTest()
{
    StringChecker stringChecker = new StringChecker();

    StringChecker spy = spy(stringChecker);

    when(spy.getSecretKey()).thenReturn("james");  // providing implementation for the method

    assertEquals(true, spy.isEqual("james"));

}
我从中学到了什么

如果您打算使用模拟对象的方法(简单地说,为模拟对象的方法提供实现),那么仅仅通过模拟对象并不能完成任务

小费

如果要查看模拟对象返回的默认值,只需在sysout中调用模拟对象的方法(不提供实现)。

希望它能帮助像我这样的人。Peace

一种无需嘲笑和附加测试用例的替代方法:

@Test
public void isEqualTest() {
    StringChecker stringChecker = new StringChecker() {
        @Override
        public String getSecretKey() {
            return "james";
        }
    };

    assertTrue(stringChacker.isEqual("james"));
    assertTrue(stringChacker.isEqual("jam"));
    assertTrue(stringChacker.isEqual("mes"));
    assertFalse(stringChacker.isEqual("oops"));
}
顺便说一句,
isEqual()
可以简化为一行:

public boolean isEqual(String name) {
    return getSecretKey().contains(name);
}

没有模拟和附加测试用例的替代方法:

@Test
public void isEqualTest() {
    StringChecker stringChecker = new StringChecker() {
        @Override
        public String getSecretKey() {
            return "james";
        }
    };

    assertTrue(stringChacker.isEqual("james"));
    assertTrue(stringChacker.isEqual("jam"));
    assertTrue(stringChacker.isEqual("mes"));
    assertFalse(stringChacker.isEqual("oops"));
}
顺便说一句,
isEqual()
可以简化为一行:

public boolean isEqual(String name) {
    return getSecretKey().contains(name);
}

我不明白。你是在问还是在说解决方案?这是一个答案。一旦你嘲笑了这个班,它就不是真实的东西(对象)再也没有了。因此
StringChecker
中的实现代码也不一样了。您在
getSecretKey
上设置了模拟返回值,但在
isEqual
上没有设置。如果您想在您的示例中进行类似的测试,可以使用mockito
spy
,在这里您可以有选择地只模拟一个类的一部分,并保持其余部分为“real”。我是这样做的假设因为我使用了when()。然后返回。当它在模拟类中被调用时,它会给我字符串值。我在这里错了吗?是的,这是可行的,但是
stringChecker.isEqual()在模拟中没有实现代码,所以不设置它就调用它是没有意义的(在这种情况下,设置它,然后测试它毫无意义:)我不明白。你是在问还是在说解决方案?这是一个答案。一旦你嘲笑了这个类,它就不是真实的东西(对象)再也没有了。因此
StringChecker
中的实现代码也不一样了。您在
getSecretKey
上设置了模拟返回值,但在
isEqual
上没有设置。如果您想在您的示例中进行类似的测试,可以使用mockito
spy
,在这里您可以有选择地只模拟一个类的一部分,并保持其余部分为“real”。我是这样做的假设因为我使用了when()。然后返回。当它在模拟类中被调用时,它会给我字符串值。我在这里错了吗?是的,这是可行的,但是
stringChecker.isEqual()在模拟中没有实现代码,所以不设置它就调用它是没有意义的(在这种情况下,设置它,然后在井上测试它是没有意义的:)