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

如何为指定Java方法编写Mockito测试用例

如何为fetchLocations()方法编写Mockito测试用例

让我一步步帮你补全这个测试用例,先拆解下你的fetchLocations()方法里的关键依赖——这些都是我们需要mock的对象:

  • config:提供用户名、密码、OData接口地址等配置项
  • BasicAuthRestTemplate:发起HTTP请求的模板类(注意你原方法里是直接new的实例,这会给测试带来麻烦,后面我会讲两种处理方式)
  • StringUtility.changeUIFieldCase():字符串格式转换工具方法
  • map.Locations():把处理后的字符串映射为Locations对象列表的工具方法

方案1:先重构原代码(推荐,让代码更易测试)

首先,把BasicAuthRestTemplate的实例化改为依赖注入,而不是在方法内直接new,这样Mockito就能轻松mock它:

// 重构后的原方法,通过构造函数注入依赖
private final Config config;
private final BasicAuthRestTemplate restTemplate;

public YourService(Config config, BasicAuthRestTemplate restTemplate) {
    this.config = config;
    this.restTemplate = restTemplate;
}

public List<Locations> fetchLocations() {
    String locationsOData = restTemplate.getForObject(config.getOdataUrl() + config.getLocations(), String.class);
    String results = StringUtility.changeUIFieldCase(locationsOData); // 修正原代码里的变量名笔误
    return map.Locations(results);
}

现在可以写标准的Mockito测试了:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class YourServiceTest {

    @Mock
    private Config config; // mock配置类

    @Mock
    private BasicAuthRestTemplate restTemplate; // mock REST请求模板

    @InjectMocks
    private YourService yourService; // 注入被测业务类

    @Test
    public void fetchLocationsTest() throws Exception {
        // 1. 准备测试数据
        List<Locations> expectedLocations = new ArrayList<>();
        expectedLocations.add(new Locations("北京")); // 假设Locations有对应构造方法
        String mockODataResponse = "{\"locations\": [{\"name\": \"北京\"}]}";
        String processedString = "{\"locations\": [{\"Name\": \"北京\"}]}"; // 模拟格式转换后的结果

        // 2. 配置mock对象的行为
        // 配置config返回预设的配置值
        when(config.getUsername()).thenReturn("testUser");
        when(config.getPassword()).thenReturn("testPass");
        when(config.getOdataUrl()).thenReturn("https://example.com/odata/");
        when(config.getLocations()).thenReturn("Locations");

        // 配置restTemplate返回模拟的OData响应
        when(restTemplate.getForObject(eq("https://example.com/odata/Locations"), eq(String.class)))
                .thenReturn(mockODataResponse);

        // 模拟静态工具方法StringUtility.changeUIFieldCase
        try (var mockedUtility = Mockito.mockStatic(StringUtility.class)) {
            mockedUtility.when(() -> StringUtility.changeUIFieldCase(mockODataResponse))
                    .thenReturn(processedString);

            // 模拟静态工具方法map.Locations
            try (var mockedMap = Mockito.mockStatic(map.class)) {
                mockedMap.when(() -> map.Locations(processedString))
                        .thenReturn(expectedLocations);

                // 3. 调用被测方法
                List<Locations> actualLocations = yourService.fetchLocations();

                // 4. 验证结果和交互
                assertEquals(expectedLocations, actualLocations);
                mockedUtility.verify(() -> StringUtility.changeUIFieldCase(mockODataResponse));
                mockedMap.verify(() -> map.Locations(processedString));
            }
        }
    }
}

方案2:不修改原代码,用PowerMock mock构造方法

如果你暂时不能修改原代码,只能用PowerMock来mockBasicAuthRestTemplate的构造函数:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;

@RunWith(PowerMockRunner.class)
@PrepareForTest({YourService.class, StringUtility.class, map.class}) // 声明需要处理的类
public class YourServiceTest {

    @Mock
    private Config config;

    @Mock
    private BasicAuthRestTemplate mockRestTemplate;

    @Test
    public void fetchLocationsTest() throws Exception {
        // 1. 准备测试数据
        List<Locations> expectedLocations = new ArrayList<>();
        expectedLocations.add(new Locations("北京"));
        String mockODataResponse = "{\"locations\": [{\"name\": \"北京\"}]}";
        String processedString = "{\"locations\": [{\"Name\": \"北京\"}]}";

        // 2. 配置mock行为
        // 配置config返回预设值
        when(config.getUsername()).thenReturn("testUser");
        when(config.getPassword()).thenReturn("testPass");
        when(config.getOdataUrl()).thenReturn("https://example.com/odata/");
        when(config.getLocations()).thenReturn("Locations");

        // mock BasicAuthRestTemplate的构造函数,返回我们的mock实例
        PowerMockito.whenNew(BasicAuthRestTemplate.class)
                .withArguments("testUser", "testPass")
                .thenReturn(mockRestTemplate);

        // 配置mockRestTemplate的getForObject方法
        when(mockRestTemplate.getForObject(eq("https://example.com/odata/Locations"), eq(String.class)))
                .thenReturn(mockODataResponse);

        // 模拟静态工具方法
        PowerMockito.mockStatic(StringUtility.class);
        when(StringUtility.changeUIFieldCase(mockODataResponse)).thenReturn(processedString);

        PowerMockito.mockStatic(map.class);
        when(map.Locations(processedString)).thenReturn(expectedLocations);

        // 3. 调用被测方法
        YourService yourService = new YourService(config); // 假设构造函数传入config
        List<Locations> actualLocations = yourService.fetchLocations();

        // 4. 验证结果和构造函数调用
        assertEquals(expectedLocations, actualLocations);
        PowerMockito.verifyNew(BasicAuthRestTemplate.class)
                .withArguments("testUser", "testPass");
    }
}

几个关键注意点:

  • 原代码里StringUtility.changeUIFieldCase(locations)是笔误,应该改为locationsOData,否则会出现变量未定义的错误
  • 如果map是实例方法而非静态方法,只需要mockmap的实例对象,不需要使用mockStatic
  • 测试时要确保所有外部依赖都被正确mock,避免触发真实的HTTP请求或工具方法逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:38:50