如何 override/replace 在父 class 中声明的@MockBean 字段与 @Autowired 真实 bean
How to override/replace @MockBean field declared in the parent class with @Autowired real bean
为了避免 Spring 上下文一次又一次地重新加载,我已将 @MockBean
带注释的注入移动到父级 class,类似这样。
@SpringBootTest
.......
public abstract BaseTest {
@MockBean
protected OneService oneService;
这用于测试 classes,它需要 OneService
的模拟。但是,对于我也想从 BaseTest
扩展的测试,但是通过 @Autowired
注入真正的 OneService
将不起作用,因为它将继承 BaseTest
的模拟注入].
public AnotherTest extends BaseTest {
@Autowired
protected OneService oneService;
即使我使用了 @Autowired
注释,oneService
字段将是从 BaseTest
.
继承的模拟实例
有没有办法强制注入使用自动装配?
在 Java 中,技术上无法覆盖字段。当您在 subclass 中声明具有相同名称的字段时,该字段会隐藏 superclass 中具有相同名称的字段。所以这是一个障碍。
第二个障碍源于这样一个事实,即如果 superclass 配置,Spring Boot 的测试支持无法关闭 subclass 中的 bean 模拟通过 @MockBean
.
的嘲笑
因此,解决方案是通过在 superclass 中通过 @Autowired
注入真正的 bean,然后在子class.
- 在 superclass 中声明
@Autowired
字段,但不要在 subclass 中重新声明该字段。
- 在子class级别声明
@MockBean
class,指定要模拟的classes(即bean类型)。
最后一步导致继承字段在子class中注入模拟。
以下两个 class 在实践中演示了此技术。
@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";
}
}
}
@MockBean(classes = BaseTests.Service.class)
class MockBeanTests extends BaseTests {
@BeforeEach
void setUpMock() {
when(service.getMessage()).thenReturn("mock");
}
@Test
@Override
void service() {
assertThat(service.getMessage()).isEqualTo("mock");
}
}
为了避免 Spring 上下文一次又一次地重新加载,我已将 @MockBean
带注释的注入移动到父级 class,类似这样。
@SpringBootTest
.......
public abstract BaseTest {
@MockBean
protected OneService oneService;
这用于测试 classes,它需要 OneService
的模拟。但是,对于我也想从 BaseTest
扩展的测试,但是通过 @Autowired
注入真正的 OneService
将不起作用,因为它将继承 BaseTest
的模拟注入].
public AnotherTest extends BaseTest {
@Autowired
protected OneService oneService;
即使我使用了 @Autowired
注释,oneService
字段将是从 BaseTest
.
有没有办法强制注入使用自动装配?
在 Java 中,技术上无法覆盖字段。当您在 subclass 中声明具有相同名称的字段时,该字段会隐藏 superclass 中具有相同名称的字段。所以这是一个障碍。
第二个障碍源于这样一个事实,即如果 superclass 配置,Spring Boot 的测试支持无法关闭 subclass 中的 bean 模拟通过 @MockBean
.
因此,解决方案是通过在 superclass 中通过 @Autowired
注入真正的 bean,然后在子class.
- 在 superclass 中声明
@Autowired
字段,但不要在 subclass 中重新声明该字段。 - 在子class级别声明
@MockBean
class,指定要模拟的classes(即bean类型)。
最后一步导致继承字段在子class中注入模拟。
以下两个 class 在实践中演示了此技术。
@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";
}
}
}
@MockBean(classes = BaseTests.Service.class)
class MockBeanTests extends BaseTests {
@BeforeEach
void setUpMock() {
when(service.getMessage()).thenReturn("mock");
}
@Test
@Override
void service() {
assertThat(service.getMessage()).isEqualTo("mock");
}
}