测试仓库Spring Boot集成测试 – 模拟返回null

huangapple go评论159阅读模式
英文:

Testing RepositorSpring Boot Integration Test - mock returns null

问题

我在集成测试我的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的接口,以及一个Service类。所有这些都是通过lombok的RequiredAllArgs构造函数进行注入的。

在我的测试中,我正在与H2数据库进行通信,这很好运行,我还想模拟pnSvc

这是我的测试类:

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

    @Autowired
    private DeviceTokenRepository dtRepo;
    @Autowired
    private PushNotificationRepository pnRepo;
    @MockBean //我们模拟这个依赖,因为我们不想发送实际通知
    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,因为它已经被弃用。

英文:

I'm having trouble with integration testing my SpringBoot application.

This is the basic structure of my class under test:

@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&lt;MiddlemanResponse&gt; send() {
    List&lt;MiddlemanResponse&gt; middlemanResponses = pnSvc.sendAll(dtRepo.findBySendStatus(DeviceTokenEntity.Status.SCHEDULED));

    return middlemanResponses;
}

}

As you can see it depends on two repositories which are interfaces extending from JpaRepository and a Service-class. All of them are injected via lombok RequiredAllArgs-constructor.

Inside my test I am communicating with an H2 database which works fine and also I want to mock the pnSvc.

Here is my testclass:

@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, &quot;message&quot;, &quot;customString&quot;, 1L, &quot;metadata&quot;);
DeviceTokenEntity deviceToken = new DeviceTokenEntity(FIRST_DEVICE_TOKEN_ID, &quot;deviceToken&quot;,  pushNotification, DeviceTokenEntity.Platform.IPHONE, &quot;applicationType&quot;,&quot;brandId&quot;, DeviceTokenEntity.Status.SCHEDULED);

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

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

@Test
public void sendOneSuccessTest() {
    List&lt;MiddlemanResponse&gt; responses = underTest.send();

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

}

Unfortunatly the mocked method pnSvc.sendAll(...) returns null, therefore the List of MiddlemanResponse is empty and my test fails with:

org.opentest4j.AssertionFailedError: expected: &lt;1&gt; but was: &lt;0&gt;
Expected :1
Actual   :0

My expectation is that the mocked method should return the set value List.of(new MiddlemanResponse(deviceToken, &quot;response_message&quot;).

SOLUTION
Thanks to dbl and Gianluca Musa for your replies I went with Gianluca Musa's approach of using any() instead of passing an actual parameter
-> pnSvc.sendAll(any()) when mocking the response

Also I did not use Gianluca Musa's proposed org.mockito.Matchers.any
but rather org.mockito.Mockito.any because of its deprecaion.

答案1

得分: 2

可能的错误是模拟的过滤器不正确,您可以使用通用选择器来模拟 sendAll (),请尝试这样做:

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

Probably the mistake is that the filter for the mock is incorrect, you can use a generic selector to simulate sendAll (), try this

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

huangapple
  • 本文由 发表于 2020年8月27日 15:59:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/63611611.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定