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.
CONTROLLER:
@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));
}
}
TEST:
@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());
}
APPLICATION:
@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:
APPLICATION FAILED TO START
Description:
A component required a bean named 'entityManagerFactory' that could not be found.
Action:
Consider defining a bean named 'entityManagerFactory' in your configuration.
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.
Hello there is an excellent link on this post: EntityManagerFactory not found in SpringBoot
You could check your spring boot jpa integration and have some good tips to set up your environment.
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
and@EntityScan
onto a separate JPA-specific configuration class@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.There's some more information about this in Spring Boot's reference documentation where it says the following:
In this particular case, the configuration setting that is specific to a particular area is
@EnableJpaRepositories
.