问题描述
@WebMvcTest
和 @MockBean
似乎没有按预期工作.也许我遗漏了什么......我有一个带有一些依赖项的控制器,我正在用 @MockBean
模拟,但应用程序无法启动,因为它找不到另一个我认为不需要的 bean在这种情况下.
It seems that @WebMvcTest
and @MockBean
are not working as expected. Maybe I'm missing something... I have a controller with some dependencies I'm mocking with @MockBean
, but the application fails to start because it cannot find another bean that I think should not be required in this case.
控制器:
@RestController
public class ExchangeRateStoreController {
private AddExchangeRate addExchangeRate;
private AddExchangeRateRequestAdapter addExchangeRateRequestAdapter;
private GetExchangeRate getExchangeRate;
private GetExchangeRateRequestAdapter getExchangeRateRequestAdapter;
@Autowired
public ExchangeRateStoreController(ExchangeRateRepository exchangeRateRepository, ExchangeRateDateValidator exchangeRateDateValidator, ExchangeRateView exchangeRateView) {
addExchangeRate = new AddExchangeRate(exchangeRateRepository, exchangeRateDateValidator);
addExchangeRateRequestAdapter = new AddExchangeRateRequestAdapter();
getExchangeRate = new GetExchangeRate(exchangeRateView);
getExchangeRateRequestAdapter = new GetExchangeRateRequestAdapter();
}
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public void create(@RequestBody AddExchangeRateRequest addExchangeRateRequest) {
addExchangeRate.execute(addExchangeRateRequestAdapter.toCommand(addExchangeRateRequest));
}
}
测试:
@RunWith(SpringRunner.class)
@WebMvcTest(ExchangeRateStoreController.class)
public class ExchangeRateStoreControllerTest {
@Autowired
private MockMvc mvc;
@MockBean
ExchangeRateRepository exchangeRateRepository;
@MockBean
ExchangeRateDateValidator exchangeRateDateValidator;
@MockBean
ExchangeRateView exchangeRateView;
@Test
public void givenValidExchangeRateCommand_whenCreate_thenOK() throws Exception {
String validRequestBody = "{\"from\":\"EUR\",\"to\":\"USD\",\"amount\":1.2345,\"date\":\"2018-11-19\"}";
doNothing().when(exchangeRateDateValidator).validate(any());
doNothing().when(exchangeRateRepository).save(any());
mvc.perform(post("/").content(validRequestBody).contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isCreated());
}
应用:
@SpringBootApplication
@EnableJpaRepositories("com...exchangerate.store.infrastructure.persistence")
@EntityScan("com...exchangerate.store.infrastructure.persistence")
@ComponentScan(basePackages = {"com...exchangerate.store.infrastructure", "com...exchangerate.store.application"} )
public class ExchangeRateStoreApplication {
public static void main(String[] args) {
SpringApplication.run(ExchangeRateStoreApplication.class, args);
}
}
运行测试时出现的错误:
And the error I get when run the test:
应用程序无法启动
说明:
一个组件需要一个名为entityManagerFactory"的 bean,它可以找不到.
A component required a bean named 'entityManagerFactory' that could not be found.
操作:
考虑定义一个名为 'entityManagerFactory' 的 bean配置.
Consider defining a bean named 'entityManagerFactory' in your configuration.
但是,如您所见,entityManagerFactory
不是控制器的依赖项.那么,为什么测试要尝试加载这个 bean?我正在嘲笑所有控制器依赖项,所以我认为它不应该这样做.
But, as you can see, entityManagerFactory
is not a controller's dependency. So, why is the test trying to load this bean? I'm mocking all the controller dependencies, so I think it shouldn't do this.
推荐答案
问题是由您在应用程序的主类上使用 @EnableJpaRepositories
引起的.通过将它放在主类上,您表明必须始终启用 JPA 存储库,无论您尝试测试哪个特定的功能部分.
The problem's caused by your use of @EnableJpaRepositories
on your application's main class. By placing it on the main class, you're indicating that JPA repositories must always be enabled, irrespective of which particular slice of functionality you're trying to test.
您可以通过执行以下操作之一来解决您的问题:
You can fix your problem by doing one of the following:
- 将
@EnableJpaRepositores
和@EntityScan
移到单独的 JPA 特定配置类上 - 删除
@EnableJpaRepositories
和@EntityScan
并依赖自动配置的默认值.为此,您的存储库和实体必须位于主类包的子包中.
- Move
@EnableJpaRepositores
and@EntityScan
onto a separate JPA-specific configuration class - Remove
@EnableJpaRepositories
and@EntityScan
and rely on the auto-configured defaults. For this to work, your repositories and entities will have to be in a sub-package of your main class's package.
Spring Boot 的 参考文档 其内容如下:
There's some more information about this in Spring Boot's reference documentation where it says the following:
如果您使用测试注释来测试应用程序的更具体部分,则应避免在主方法的应用程序类中添加特定于特定区域的配置设置.
在这种特殊情况下,特定于特定区域的配置设置是 @EnableJpaRepositories
.
In this particular case, the configuration setting that is specific to a particular area is @EnableJpaRepositories
.
这篇关于SpringBoot @WebMvcTest 和 @MockBean 没有按预期工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!