Mockito模拟返回值并验证它

时间:2014-02-28 15:30:54

标签: java unit-testing mocking mockito

我有这个类,想要创建一个模拟来返回并验证返回值“50”:
QAService.java:

@Path("/QAService")
public class QAService {
@GET()
//@Path("/")
@Produces("text/plain")
public String getServiceInfo() {
    return "50";
}

我对定义模拟的理解是我可以创建一个实现类的假对象和模拟函数,但是我可以测试接口。

仍然我正在创建此测试来测试没有接口的模拟。我如何验证?:
QAServiceTest.java:

public class QAServiceTest {

    @Test
    public void getserviceTest () {

    QAService qasmock = mock(QAService.class);
    when(qasmock.getServiceInfo()).thenReturn("50");
    String expected = "50";
    assertEquals(expected, qasmock.getServiceInfo());
    }
}

2 个答案:

答案 0 :(得分:17)

让我们直接得到几个定义,首先:

  • 单元测试是您编写的一小段代码,用于确保您开发的系统运行正常。单元测试通常在JUnit这样的框架中创建,但不需要。例如,单元测试将assertEquals(5, calculator.add(2, 3))

  • mock 是对真实系统的模仿,通常用于单元测试。模拟通常在MockitoEasyMock等框架中创建,但不需要。模拟是“测试双重”的一种形式 - 用于代替实际系统的代码的通用术语,用于测试目的 - 而Martin Fowler在名为"Mocks Aren't Stubs"的文章中更准确地定义它们。

    < / LI>
  • 在编写单元测试时,您尝试测试单个单元,通常称为受测试系统 SUT 。每个测试可能都有一个不同的系统正在测试中,关键是您在测试中测试的代码是您的真实的,实际的代码,而不是任何类型的模拟或虚假实现。

  • 在复杂的应用程序中,您的类可能需要与可能编写或未编写或编译的其他类协作,这些类通常称为依赖项。任何给定的类或系统可能都有自己的依赖项,并且可能是其他系统的依赖项。模拟框架适用于模拟这些依赖项,而不是模拟被测系统。


对于您的示例,QAService是您正在编写的主类(被测系统),QAServiceTest是该系统的单元测试。 不一定需要嘲笑。

假设QAService依赖于另一个尚未编写的类,称为“StorageService”。在编写QAService测试之前,您不一定要等待StorageService工作,因此不使用真正的StorageService,而是使用 mock 。同样,在名为QAServiceTest的单元测试中,您使用真正的 QAService并模拟其依赖 StorageService。

即使您没有编写StorageService,您也可能对QAService如何使用该类有所期待。也许你知道当你致电storageService.store(qaRecord)时,它应该返回一个数字ID,如101。即使代码不起作用,您也可以创建一个Mockito mockStorageService,并按照以下方式进行准备:

when(mockStorageService.store(expectedQARecord)).thenReturn(101);

现在让我们假设在测试结束时,您要确保您正在测试的QAService方法绝对会调用storageService.delete(101)。 Mockito mockStorageService会像这样检查:

verify(mockStorageService).delete(101);

通常不需要验证使用when生成的语句,因为除非被测系统正确调用mock以获取返回值(此处为101),否则测试不太可能成功。

现在假设您已经编写了另一个名为QAApplication的代码块,您正在一个名为QAApplicationTest的单元测试中进行测试,该测试依赖于QAService。您可能没有完成或测试QAService,并且使用真正的QAService需要StorageService,因此您在单元测试中使用 mock QAService和真正的 QAApplication 称为QAApplicationTest。


所以,总而言之,模拟在单元测试中运行来模拟系统中的依赖 。在您的情况下,QAServiceTest不需要模拟QAService,但可能用于模拟QAService的依赖项。如果你确实需要一个模拟的QAService,那么在测试另一个QAService本身就是依赖的类时你需要它。

答案 1 :(得分:11)

Junit只会运行使用@Test注释的方法,因此请添加

@Test
public void getserviceTest () {
    QAService qasmock = mock(QAService.class);
    when(qasmock.getServiceInfo()).thenReturn("50");
    String expected = "50";
    assertEquals(expected, qasmock.getServiceInfo());
}

另外,你应该verify()你的模拟期望实际发生了。

verify(qasmock, times(1)).getServiceInfo();

请注意,您似乎想要测试QAService,但实际上您并没有这样做。你只是在测试一个模拟器。那不是一回事。

自己创建QAService对象并使用它。