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

JUnit测试中@Value注入aws.s3.bucketName值为Null的解决求助

解决JUnit测试中@Value注入属性为Null的问题

你遇到的问题根源是:使用MockitoExtension时,Spring容器并未启动,Mockito的@InjectMocks只会注入标注了@Mock的Bean,不会处理@Value注解的属性注入,导致bucketName为null。以下是三种直接可行的解决方法:


方法一:反射直接设置属性值(最适合单元测试)

用Spring Test提供的ReflectionTestUtils工具,直接给私有字段赋值,无需修改被测试类代码:

@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
public class AsyncPublisherServiceImplTest {

    @InjectMocks
    private AsyncPublisherServiceImpl asyncPublisherServiceImpl;

    @Mock
    private AsyncPublisherDao dao;
    @Mock
    private AsyncUtil asyncUtil;
    @Mock
    private ClientListenerService techpulseservice;

    @BeforeEach
    void setUp() {
        // 直接给bucketName赋值
        ReflectionTestUtils.setField(asyncPublisherServiceImpl, "bucketName", "hpmap-pro-development-os-asyncmulti");
    }

    @Test
    void publish() {
        String link = null;
        PublisherRequest PublisherRequest = RequestUtils.getPublisherRequest();

        lenient().when(dao.isValidCount(ConstantsTest.UUID)).thenReturn(true);
        File file = new File(AsyncUtil.sanitizePathandfilename(ConstantsTest.UUID + ".zip"));
        assertNotNull(asyncPublisherServiceImpl.publish(PublisherRequest.getUuid(), ConstantsTest.UnitOfWorkId));
    }
}

方法二:启动Spring上下文加载配置(适合集成测试)

如果需要加载真实的配置文件,用@SpringBootTest启动Spring容器,让Spring自动处理@Value注入:

@SpringBootTest
@MockitoSettings(strictness = Strictness.LENIENT)
public class AsyncPublisherServiceImplTest {

    @Autowired
    private AsyncPublisherServiceImpl asyncPublisherServiceImpl;

    @MockBean
    private AsyncPublisherDao dao;
    @MockBean
    private AsyncUtil asyncUtil;
    @MockBean
    private ClientListenerService techpulseservice;

    @Test
    void publish() {
        String link = null;
        PublisherRequest PublisherRequest = RequestUtils.getPublisherRequest();

        lenient().when(dao.isValidCount(ConstantsTest.UUID)).thenReturn(true);
        File file = new File(AsyncUtil.sanitizePathandfilename(ConstantsTest.UUID + ".zip"));
        assertNotNull(asyncPublisherServiceImpl.publish(PublisherRequest.getUuid(), ConstantsTest.UnitOfWorkId));
    }
}

注意:这里用@MockBean替代@Mock,目的是将Mock对象注入到Spring容器中。


方法三:重构代码,用配置类替代直接@Value(推荐长期方案)

将配置属性封装到配置类中,通过构造注入传入被测试类,提升代码可测试性:

1. 创建S3配置类

@Configuration
@ConfigurationProperties(prefix = "aws.s3")
public class S3Config {
    private String bucketName;
    private String region;

    // getter、setter
    public String getBucketName() { return bucketName; }
    public void setBucketName(String bucketName) { this.bucketName = bucketName; }
    public String getRegion() { return region; }
    public void setRegion(String region) { this.region = region; }
}

2. 修改被测试类为构造注入

@Service
@Transactional
public class AsyncPublisherServiceImpl implements AsyncPublisherService {
    Logger logger = LoggerFactory.getLogger(this.getClass().getName());
    private final AsyncPublisherDao dao;
    private final AsyncUtil asyncUtil;
    private final ClientListenerService techpulseservice;
    private final String bucketName;

    // 构造注入替代@Autowired和@Value
    public AsyncPublisherServiceImpl(AsyncPublisherDao dao, AsyncUtil asyncUtil, ClientListenerService techpulseservice, S3Config s3Config) {
        this.dao = dao;
        this.asyncUtil = asyncUtil;
        this.techpulseservice = techpulseservice;
        this.bucketName = s3Config.getBucketName();
    }

    // 原有业务逻辑代码不变
}

3. 测试类直接传入配置实例

@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
public class AsyncPublisherServiceImplTest {

    private AsyncPublisherServiceImpl asyncPublisherServiceImpl;

    @Mock
    private AsyncPublisherDao dao;
    @Mock
    private AsyncUtil asyncUtil;
    @Mock
    private ClientListenerService techpulseservice;

    @BeforeEach
    void setUp() {
        S3Config s3Config = new S3Config();
        s3Config.setBucketName("hpmap-pro-development-os-asyncmulti");
        // 直接通过构造方法传入所需依赖
        asyncPublisherServiceImpl = new AsyncPublisherServiceImpl(dao, asyncUtil, techpulseservice, s3Config);
    }

    @Test
    void publish() {
        String link = null;
        PublisherRequest PublisherRequest = RequestUtils.getPublisherRequest();

        lenient().when(dao.isValidCount(ConstantsTest.UUID)).thenReturn(true);
        File file = new File(AsyncUtil.sanitizePathandfilename(ConstantsTest.UUID + ".zip"));
        assertNotNull(asyncPublisherServiceImpl.publish(PublisherRequest.getUuid(), ConstantsTest.UnitOfWorkId));
    }
}

内容的提问来源于stack exchange,提问作者S.R.D

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 01:22:10