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

如何使用Mockito Mock Spring中通过@Value结合SpEL表达式注入的Map对象

嘿,这个场景我熟!给你分享几种在Spring里用Mockito(配合Spring测试工具)Mock @Value注入的Map的实用方案,按需选就行:

方案1:纯单元测试——用ReflectionTestUtils直接赋值(最快最直接)

如果只是想单独测试目标类,不需要加载Spring上下文,用Mockito的@InjectMocks创建实例,再通过Spring的ReflectionTestUtils把我们自定义的Map直接塞进私有字段里就行:

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.test.util.ReflectionTestUtils;

import java.util.HashMap;
import java.util.Map;

import static org.junit.jupiter.api.Assertions.assertEquals;

@ExtendWith(MockitoExtension.class)
public class PatientServiceTest {

    @InjectMocks
    private PatientService patientService; // 你的目标业务类

    @Test
    void testGetPatientTypeCode() {
        // 构建测试用的Map数据
        Map<String, Integer> testPatientTypes = new HashMap<>();
        testPatientTypes.put("ADULT", 1);
        testPatientTypes.put("CHILD", 2);

        // 直接给私有字段赋值
        ReflectionTestUtils.setField(patientService, "patientTypes", testPatientTypes);

        // 验证业务逻辑
        assertEquals(1, patientService.getPatientTypeCode("ADULT"));
        assertEquals(2, patientService.getPatientTypeCode("CHILD"));
    }
}

方案2:Spring集成测试——用@TestPropertySource指定属性值

如果你的测试需要加载完整的Spring上下文(比如集成测试),直接在测试类上用@TestPropertySource配置属性,Spring会自动把解析后的Map注入到目标类:

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;

import static org.junit.jupiter.api.Assertions.assertEquals;

@SpringBootTest
@TestPropertySource(properties = {
        "patientTypes.ADULT=1",
        "patientTypes.CHILD=2"
})
public class PatientServiceIntegrationTest {

    @Autowired
    private PatientService patientService;

    @Test
    void testGetPatientTypeCode() {
        assertEquals(1, patientService.getPatientTypeCode("ADULT"));
        assertEquals(2, patientService.getPatientTypeCode("CHILD"));
    }
}

这里要注意,你用的@Value("#{${patientTypes}}")是SpEL表达式,Spring会自动把patientTypes.*格式的属性解析成Map,直接写键值对就行。

方案3:复杂场景——自定义PropertySourcesPlaceholderConfigurer

如果需要在多个测试中复用这套Map配置,或者有更复杂的属性逻辑,可以自定义一个测试配置类,提供自定义的属性源:

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;

import java.util.Map;

import static org.junit.jupiter.api.Assertions.assertEquals;

@SpringBootTest
public class PatientServiceComplexTest {

    @Autowired
    private PatientService patientService;

    // 测试专属配置类
    @Configuration
    static class TestConfig {
        @Bean
        @Primary
        public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
            PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
            // 直接设置解析后的Map
            Map<String, Object> testProperties = Map.of(
                "patientTypes", Map.of("ADULT", 1, "CHILD", 2)
            );
            PropertySource<?> propertySource = new MapPropertySource("testProps", testProperties);
            configurer.getPropertySources().addFirst(propertySource);
            return configurer;
        }
    }

    @Test
    void testGetPatientTypeCode() {
        assertEquals(1, patientService.getPatientTypeCode("ADULT"));
        assertEquals(2, patientService.getPatientTypeCode("CHILD"));
    }
}

小提醒

  • 方案1是纯单元测试,不加载Spring上下文,执行速度最快,适合单类独立测试。
  • 方案2和3需要加载Spring上下文,适合需要依赖其他Spring Bean的集成测试场景。
  • ReflectionTestUtils是spring-test包提供的工具类,确保你的测试依赖里包含这个包。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 12:02:49