【问题标题】:Testing RepositorSpring Boot Integration Test - mock returns null测试 RepositorSpring Boot 集成测试 - 模拟返回 null
【发布时间】:2020-12-16 01:53:44
【问题描述】:

我在集成测试我的 SpringBoot 应用程序时遇到问题。

这是我测试类的基本结构:

@Controller
@RequiredArgsConstructor
public class PushNotificationController {
    private final PushNotificationService pnSvc;
    private final PushNotificationRepository pnRepo;
    private final DeviceTokenRepository dtRepo;

/**
 * This method sends all PushNotifications from memory,
 * which are not sent yet.
 */
public List<MiddlemanResponse> send() {
    List<MiddlemanResponse> middlemanResponses = pnSvc.sendAll(dtRepo.findBySendStatus(DeviceTokenEntity.Status.SCHEDULED));

    return middlemanResponses;
}

}

如您所见,它依赖于两个存储库,它们是从 JpaRepository 扩展的接口和一个服务类。它们都是通过 lombok RequiredAllArgs-constructor 注入的。

在我的测试中,我正在与一个运行良好的 H2 数据库进行通信,并且我想模拟 pnSvc

这是我的测试类:

@RunWith(SpringRunner.class)
@SpringBootTest
public class PushNotificationControllerIntegrationTest {
@Autowired
private PushNotificationController underTest;

@Autowired
private DeviceTokenRepository dtRepo;
@Autowired
private PushNotificationRepository pnRepo;
@MockBean //we mock this dependency because we dont want to send actual notifications
private PushNotificationService pnSvc;

//testvalues
private final Long FIRST_PUSH_NOTIFICATION_ID = 1L;
private final Long FIRST_DEVICE_TOKEN_ID = 1L;
PushNotificationEntity pushNotification = new PushNotificationEntity(FIRST_PUSH_NOTIFICATION_ID, "message", "customString", 1L, "metadata");
DeviceTokenEntity deviceToken = new DeviceTokenEntity(FIRST_DEVICE_TOKEN_ID, "deviceToken",  pushNotification, DeviceTokenEntity.Platform.IPHONE, "applicationType","brandId", DeviceTokenEntity.Status.SCHEDULED);

@Before
public void setUp() throws MiddlemanException {
    when(pnSvc.sendAll(dtRepo.findBySendStatus(DeviceTokenEntity.Status.SCHEDULED))).thenReturn(List.of(new MiddlemanResponse(deviceToken, "response_message")));

    pnRepo.save(pushNotification);
    dtRepo.save(deviceToken);
}

@Test
public void sendOneSuccessTest() {
    List<MiddlemanResponse> responses = underTest.send();

    assertEquals(1, responses.size());
}

}

不幸的是,模拟方法 pnSvc.sendAll(...) 返回 null,因此 MiddlemanResponse 列表为空,我的测试失败:

org.opentest4j.AssertionFailedError: expected: <1> but was: <0>
Expected :1
Actual   :0

我的期望是被模拟的方法应该返回设置值List.of(new MiddlemanResponse(deviceToken, "response_message")

解决方案 感谢 dbl 和 Gianluca Musa 的回复,我采用了 Gianluca Musa 的方法,即使用 any() 而不是传递实际参数 -> pnSvc.sendAll(any()) 模拟响应时

我也没有使用 Gianluca Musa 提出的org.mockito.Matchers.any 而是org.mockito.Mockito.any,因为它已弃用。

【问题讨论】:

  • Mocks 默认返回null,除非您指定要返回的特定值...
  • when(that.doThis(someVal).thenReturn(blah) 的情况下,您应该使用匹配器...例如when(that.doThis(eq(someVal)).thenReturn(blah)

标签: java spring-boot integration-testing spring-boot-test


【解决方案1】:

可能错误是mock的过滤器不正确,可以使用泛型选择器模拟sendAll(),试试这个

when(pnSvc.sendAll(org.mockito.Mockito.any()).thenReturn(List.of(new MiddlemanResponse(deviceToken, "response_message")));

【讨论】:

  • any 也是一个选项,但根据测试需要,他可以更加具体。
  • 这行得通,但我使用 org.mockito.Mockito.any 而不是已弃用的建议 @dbl any 对于这个测试用例就足够了
猜你喜欢
  • 1970-01-01
  • 2019-07-28
  • 1970-01-01
  • 2012-04-25
  • 1970-01-01
  • 2021-04-09
  • 2019-11-10
  • 1970-01-01
  • 2021-08-02
相关资源
最近更新 更多