问题描述
为了避免 Spring 上下文一次又一次地重新加载,我已将 @MockBean
带注释的注入移动到父类,类似这样。
@SpringBoottest
.......
public abstract BaseTest {
@MockBean
protected Oneservice oneservice;
这为需要模拟 Oneservice
的测试类提供服务。但是,对于我也想从 BaseTest
扩展的测试,但是通过 Oneservice
注入真正的 @Autowired
将不起作用,因为它将继承 {{1} }.
BaseTest
即使我使用了 public AnotherTest extends BaseTest {
@Autowired
protected Oneservice oneservice;
注释,@Autowired
字段也将是从 oneservice
继承的模拟实例。
有没有办法强制注入使用自动装配?
解决方法
在 Java 中,技术上无法覆盖字段。当您在子类中声明同名字段时,该字段会隐藏超类中的同名字段。所以这是一个障碍。
第二个障碍源于这样一个事实:如果超类通过 DateTimeFormatter fmt = DateTimeFormat.forPattern("MM/dd/yyyy HH:mm:ss").withZone(DateTimeZone.forID(
"Europe/Berlin"));
DateTime dt = fmt.parseDateTime(lastModifid);
dt.toString()
配置模拟,则 Spring Boot 的测试支持无法关闭子类中 bean 的模拟。
因此,解决方案是通过在超类中通过 @MockBean
注入真正的 bean,然后在子类中打开对特定 bean 类型的模拟来反转您正在尝试执行的操作。
- 在超类中声明
@Autowired
字段,但不要在子类中重新声明该字段。 - 在子类的类级别声明
@Autowired
,指定要模拟的类(即 bean 类型)。
最后一步导致继承的字段被注入子类中的模拟。
以下两个课程在实践中演示了这种技术。
@MockBean
@SpringBootTest(classes = BaseTests.Config.class)
class BaseTests {
@Autowired
protected Service service;
@Test
void service() {
assertThat(service.getMessage()).isEqualTo("real");
}
@Configuration
static class Config {
@Bean
Service service() {
return new Service();
}
}
static class Service {
String getMessage() {
return "real";
}
}
}