【问题标题】:How to write unit tests for this simple application如何为这个简单的应用程序编写单元测试
【发布时间】:2014-10-09 13:32:32
【问题描述】:

我有一个应用程序,其类注册为消息侦听器,它从队列接收消息,检查它的类类型是否正确(在public void onMessage(Message message) 中)并将其发送到另一个类,该类将此类转换为字符串并写入日志文件的行(public void handleMessage(MessageType m))。您将如何为此编写单元测试?

【问题讨论】:

  • 在我看来单元测试应该小而简洁,你应该有单元测试来验证一个单元是否正常工作。可能是您要求进行集成测试。
  • 也进行集成测试?你在用 maven 吗?
  • 为了避免重复答案,您可以see my answer here 类似的问题。
  • 我正在使用 Maven。也许我应该跳过单元测试并进行端到端的集成测试。
  • 我会写至少两个单元测试。一个用于验证如果消息的类型错误是否引发了预期的异常,另一个用于验证消息是否已传递给另一个类(我将模拟)。

标签: java unit-testing testing


【解决方案1】:

如果您可以将 Mockito 与 JUnit 结合使用,您的测试可能如下所示:

public void onMessage_Success() throws Excepton {
  // Arrange
  Message message = aMessage().withContent("...").create();
  File mockLogFile = mock(File.class);
  MessageHandler mockMessageHandler = mock(MessageHandler.class);
  when(mockMessageHandler).handleMessage(any(MessageType.class)
      .thenReturn("somePredefinedTestOutput");
  when(mockMessageHandler).getLogFile().thenReturn(mockLogFile);

  MessageListener sut = spy(new MessageListener());
  Whitebox.setInternalState(sut, "messageHanlder", mockMessageHandler);
  // or simply sut.setMessageHandler(mockMessageHandler); if a setter exists

  // Act
  sut.onMessage(message);

  // Assert
  assertThat(mockLogFile, contains("your desired content"));
  verify(sut, times(1)).handleMessage(any(Message.class));
}

请注意,这只是一个如何测试它的简单示例。可能还有很多其他方法可以测试功能。上面的示例展示了用于生成默认消息的典型构建器模式,默认消息接受某些值进行测试。此外,我还没有真正澄清 mockLogFile 上 contains 方法的 Hamcrest 匹配器。

正如@Keppil 在他的评论中也提到的那样,创建多个测试用例是有意义的,这些测试用例在安排和断言测试坏用例的部分略有不同


我可能解释得不够充分的是 MessageHandlergetLogFile() 方法(在您的应用程序中肯定有另一个名称)应该返回对您的 MessageHandler 实例使用的文件的引用来存储实际日志消息。因此,最好将此 mockMessageHandler 定义为 spy(new MessageHandler()) 而不是 mock(MessageHandler.class),尽管这意味着单元测试实际上是一个集成测试,因为同时测试了两个类的交互。

但总的来说,我希望你明白 - 使用 mock(Class) 为你的被测系统 (SUT) 所需的依赖项生成默认实现,如果你想包含真实世界的对象,则使用 spy(Instance)一种只有空值作为返回类型的。您可以使用 when(...).thenReturn(...)/.thenThrow(...) 或 doReturn(...).when(...) 来影响模拟对象的返回值,以防万一无效操作 f.e.

如果你有依赖注入到私有字段,你应该使用Whitebox.setInternalState(...) 将值注入到 sut 或模拟类中,如果没有公共或包私有(如果你获得重用包结构的测试模型测试类中的系统被测类)设置方法可用。

此外,verify(...) 允许您验证在执行 SUT 时是否调用了某个方法。在实际断言不是那么简单的情况下,这在这种情况下非常方便。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-06
    • 2021-03-27
    • 2021-04-07
    • 2015-06-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多