You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SpringBoot JUnit中Mock Firebase TopicManagementResponse遇null问题排查

Mock TopicManagementResponse 空值问题排查与解决

问题描述

使用Mockito.mock(TopicManagementResponse.class)Mock对象后,测试时仍提示response为空,需确认该Mock方式是否正确,以及可行的解决方法,目标是借助该对象完成Controller方法的测试。

相关代码

Controller类代码

@PostMapping("/subscribeToTopic")
public int createTopic(@RequestBody Topic topic) throws IOException, FirebaseMessagingException {
 
    String platformID = topic.getPlatformId();

    // 内部方法获取firebase messaging实例
    FirebaseMessaging firebaseMessaging = fcmInitializer.getFirebaseMessaging(platformID);
 
    // 从JSON的"topic"字段获取主题名
    String topicName = topic.getTopicName();
 
    // 校验主题名非空
    if (topicName == null || topicName.isEmpty()) {
        return 0;
    }
    TopicManagementResponse response = firebaseMessaging.subscribeToTopic(topic.getToken(), topicName);
    return response.getSuccessCount();
 
}

原测试类代码

public void createTopic(){
FirebaseMessaging firebaseMessaging = mock(FirebaseMessaging.class);
    TopicManagementResponse response = mock(TopicManagementResponse.class);

    Topic topic = new Topic();
    topic.setToken("some token");
    topic.setTopic("some topic");
    

    when(firebaseMessaging.subscribeToTopic(topic.getToken(), topic.getTopic())).thenReturn(response);

    assertEquals(response.getSuccessCount, 1);


}

问题原因分析

  1. Mock实例未注入Controller:Controller中使用的FirebaseMessaging是通过fcmInitializer.getFirebaseMessaging()获取的,而非测试中Mock的实例,导致subscribeToTopic不会返回预设的response,实际拿到null。
  2. 字段不匹配导致参数校验失败:Controller中使用topic.getTopicName()获取主题名,但测试中调用topic.setTopic("some topic"),字段名不匹配,Mock的方法调用无法触发。
  3. 未预设Mock对象的方法返回值:即使拿到TopicManagementResponse的Mock实例,未预设getSuccessCount()的返回值,调用时会返回对应类型的默认值(int类型默认0)。
  4. 测试方法缺少注解:未添加@Test注解(JUnit环境下),测试逻辑不会被执行。

修正后的测试方案

步骤1:确保Controller依赖可注入

确保Controller中的fcmInitializer通过依赖注入方式引入,比如:

@RestController
public class TopicController {
    @Autowired
    private FcmInitializer fcmInitializer;

    // 原createTopic方法...
}

步骤2:编写修正后的测试类

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class TopicControllerTest {

    @Mock
    private FcmInitializer fcmInitializer; // Mock Controller依赖的初始化类

    @Mock
    private FirebaseMessaging firebaseMessaging; // Mock FirebaseMessaging实例

    @Mock
    private TopicManagementResponse topicManagementResponse; // Mock返回对象

    @InjectMocks
    private TopicController topicController; // 注入Mock对象到Controller

    @Test
    public void createTopic_ShouldReturnSuccessCount() throws IOException, FirebaseMessagingException {
        // 构造测试用的Topic对象,确保字段匹配
        Topic topic = new Topic();
        topic.setToken("some token");
        topic.setTopicName("some topic"); // 对应Controller中的getTopicName()
        topic.setPlatformId("test-platform");

        // 预设fcmInitializer返回Mock的FirebaseMessaging
        when(fcmInitializer.getFirebaseMessaging(topic.getPlatformId())).thenReturn(firebaseMessaging);

        // 预设subscribeToTopic方法返回Mock的response
        when(firebaseMessaging.subscribeToTopic(topic.getToken(), topic.getTopicName()))
                .thenReturn(topicManagementResponse);

        // 预设response的getSuccessCount返回1
        when(topicManagementResponse.getSuccessCount()).thenReturn(1);

        // 调用Controller方法
        int result = topicController.createTopic(topic);

        // 断言返回值符合预期
        assertEquals(1, result);
    }
}

其他可行Mock方式

如果不想使用@Mock注解,也可以手动创建Mock实例并注入:

public void createTopic_ManualMock() throws IOException, FirebaseMessagingException {
    FcmInitializer mockInitializer = mock(FcmInitializer.class);
    FirebaseMessaging mockFcm = mock(FirebaseMessaging.class);
    TopicManagementResponse mockResponse = mock(TopicManagementResponse.class);

    TopicController controller = new TopicController();
    // 通过setter或者反射注入mockInitializer到controller

    when(mockInitializer.getFirebaseMessaging("test-platform")).thenReturn(mockFcm);
    when(mockFcm.subscribeToTopic("some token", "some topic")).thenReturn(mockResponse);
    when(mockResponse.getSuccessCount()).thenReturn(1);

    Topic topic = new Topic();
    topic.setToken("some token");
    topic.setTopicName("some topic");
    topic.setPlatformId("test-platform");

    assertEquals(1, controller.createTopic(topic));
}

内容的提问来源于stack exchange,提问作者akashi paul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 06:24:52