如何在@PostConstruct 之前配置@MockBean?

问题描述

我有一个服务,它有一个我想要模拟的 DataProvider

问题:服务使用 @postconstruct 中的数据提供者。但是当我使用 @MockBean 时,@postconstruct 中不存在模拟值。

我能做什么?

@Service
public class MyService {
    private List<Object> data;

    @Autowired
    private DataProvider dataProvider;
    
    @postconstruct
    public void initData() {
        data = dataProvider.getData();
    }
    
    public void run() {
        System.out.println(data); //always null in tests
    }
}


@SpringBoottest
public class Test {
    @MockBean
    private DataProvider dataProvider;

    @Test
    public void test() {
        when(dataProvider.getData()).thenReturn(mockedobjects);
        //dataProvider.init(); //this fixes it,but feels wrong
        service.run();
    }
}

解决方法

恕我直言,单元测试 MyService 将是这种特定场景的更好解决方案(在这种情况下,我不会觉得手动调用 initService 有错),但如果您坚持...>

您可以简单地覆盖此特定测试的 DataProvider bean 定义并预先模拟它,例如:

@SpringBootTest(classes = {MyApplication.class,Test.TestContext.class})
public class Test {

    @Test
    public void test() {
        service.run();
    }

    @Configuration
    static class TestContext {

        @Primary
        public DataProvider dataProvider() {
            var result = Mockito.mock(DataProvider.class);
            when(result.getData()).thenReturn(mockedObjects);
            return result;
        }
    }
}

您可能需要将 spring.main.allow-bean-definition-overriding 设置为 true 才能使上述操作生效。