SpringBoot @WebMvcTest 和 @MockBean 没有按预期工作 [英] SpringBoot @WebMvcTest and @MockBean not working as expected

查看:59
本文介绍了SpringBoot @WebMvcTest 和 @MockBean 没有按预期工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

@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:

如果您使用测试注释来测试应用程序的更具体部分,则应避免在主方法的应用程序类中添加特定于特定区域的配置设置.

If you use a test annotation to test a more specific slice of your application, you should avoid adding configuration settings that are specific to a particular area on the main method’s application class.

在这种特殊情况下,特定于特定区域的配置设置是 @EnableJpaRepositories.

In this particular case, the configuration setting that is specific to a particular area is @EnableJpaRepositories.

这篇关于SpringBoot @WebMvcTest 和 @MockBean 没有按预期工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆