SpringBoot @WebMvcTest 和 @MockBean 没有按预期工作

Posted

技术标签:

【中文标题】SpringBoot @WebMvcTest 和 @MockBean 没有按预期工作【英文标题】:SpringBoot @WebMvcTest and @MockBean not working as expected 【发布时间】:2019-04-30 16:17:06 【问题描述】:

@WebMvcTest@MockBean 似乎没有按预期工作。也许我遗漏了一些东西......我有一个控制器,它有一些依赖项,我用@MockBean 模拟,但应用程序无法启动,因为它找不到我认为在这种情况下不需要的另一个 bean。

控制器:

@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);
    

以及我在运行测试时遇到的错误:

应用程序启动失败


说明:

一个组件需要一个名为“entityManagerFactory”的bean,它可以 找不到。

行动:

考虑在你的 配置。

但是,如您所见,entityManagerFactory 不是控制器的依赖项。那么,为什么测试试图加载这个 bean?我在嘲笑所有控制器依赖项,所以我认为它不应该这样做。

【问题讨论】:

【参考方案1】:

问题是由于您在应用程序的主类上使用了@EnableJpaRepositories 引起的。通过将其放置在主类中,您表明必须始终启用 JPA 存储库,无论您尝试测试哪个特定的功能部分。

您可以通过执行以下操作之一来解决您的问题:

@EnableJpaRepositores@EntityScan 移动到单独的 JPA 特定配置类中 删除 @EnableJpaRepositories@EntityScan 并依赖自动配置的默认值。为此,您的存储库和实体必须位于主类包的子包中。

在 Spring Boot 的 reference documentation 中有一些关于此的更多信息,其中说明如下:

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

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

【讨论】:

非常感谢@andy-wilkinson!你的回答切中要害。它绝对解决了我的问题。但是,我面临一个新的相关问题。你能看看我刚刚发布的这个问题吗? -> ***.com/questions/53545831/…提前谢谢!!【参考方案2】:

你好,这篇文章有一个很好的链接:EntityManagerFactory not found in SpringBoot

您可以检查您的 spring boot jpa 集成并获得一些设置环境的好技巧。

【讨论】:

以上是关于SpringBoot @WebMvcTest 和 @MockBean 没有按预期工作的主要内容,如果未能解决你的问题,请参考以下文章

SpringBoot @WebMvcTest,自动装配 RestTemplateBuilder

SpringBoot:具有授权的 WebMvcTest

Spring Boot 2 @WebMvcTest 和 OAuth2 #oauth2.hasScope 控制器导致 IllegalArgumentException

@MockBean 不适用于带有 JUnit 5 和 Spring Boot 2 的 @WebMvcTest?

在 Spring Boot 1.4 MVC 测试中使用 @WebMvcTest 设置 MockMvc

在 Spring Boot 中禁用 @WebMvcTest 的 Spring Security 配置类