3

I have a main @SpringBootApplication which needs to scan a specific package in order to enable the JPA repositories, so I use @EnableJpaRepositories to specify that. Right now I'm implementing unit tests and I want to test the Controller component only, so I followed the tutorial in the official docs where they use @WebMvcTest(MyController.class) to test a controller with a service dependency. The problem is that this is not working for me because it is trying to load the JpaRepositories that I specify in the main Spring Boot application (when I comment the @EnableJpaRepositories in the main class the test runs without problem).

I'm guessing I need to create a specific configuration for the test class so it can ignore the main configuration (since I only want to load the Controller and mock the service layer), but I don't know how to create such. I tried adding an empty configuration, but it is still failing with the same error:

@TestConfiguration
static class TestConfig {}

This is the error I get:

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'failureTaskHandler': Unsatisfied dependency expressed through field 'myManager'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'msgManager': Unsatisfied dependency expressed through field 'inboundManager'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'inboundManager': Unsatisfied dependency expressed through field 'messageRepository'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'messageRepository' defined in com.example.MessageRepository defined in @EnableJpaRepositories declared on MonitorApplication: Cannot create inner bean '(inner bean)#45e639ee' of type [org.springframework.orm.jpa.SharedEntityManagerCreator] while setting bean property 'entityManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#45e639ee': Cannot resolve reference to bean 'entityManagerFactory' while setting constructor argument; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'entityManagerFactory' available

And my test class:

@WebMvcTest(MyController.class)
public class MyControllerTest {

  @Autowired private MockMvc mvc;

  @MockBean private MyService service;


  // Tests here

  // @Test
  // public void...


}

MyController class:

@RestController
@CrossOrigin
@RequestMapping("/api")
@Slf4j
public class MyController {

  @Autowired private MyService service;

  @PostMapping(value = "/search", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
  public @ResponseBody SearchResponse getOrders(@RequestBody SearchRequest orderSearchRequest) {
    log.info("Receiving orders request...");
    return service.getOrders(orderSearchRequest);
  }

}
v.ladynev
  • 19,275
  • 8
  • 46
  • 67
Erick Siordia
  • 171
  • 1
  • 10

2 Answers2

5

Quick solution

Remove @EnableJpaRepositories from your Spring Boot Application class. Use:

@SpringBootApplication
public class MainApplication { 

}

in place of

@SpringBootApplication
@EnableJpaRepositories
public class MainApplication { 

}

In this case Spring Boot will find Spring Data JPA on the classpath and uses auto-configuration to scan packages for the repositories.

Use @EnableJpaRepositories to scan a specific package

Use @NikolaiShevchenko solution (it is incorrect) with a separate configuration, but without explicit importing it, by @Import({ DataConfiguration.class }), (because tests will be explicitly import the configuration too) and let Spring Boot find your configuration during packages scan.

@SpringBootApplication
public class MainApplication { 

}

@Configuration
@EnableJpaRepositories(basePackages = "com.app.entities")
public class JpaConfig {

}

Important

Don't forget to add basePackages property, if you put your configuration in a separate package.

v.ladynev
  • 19,275
  • 8
  • 46
  • 67
  • 1
    Separating the `@EnableJpaRepositories` in a separate configuration class indeed does the trick. I wonder if that is a bug in the test engine. – Bruno Medeiros Aug 21 '23 at 07:34
  • @BrunoMedeiros It is not a bug. A test import all the configuration form `@SpringBootApplication` class. It doesn't touch a separate database configuration. – v.ladynev Aug 21 '23 at 12:23
1

Declare separate configuration

@Configuration
@EnableJpaRepositories
public class DataConfiguration { ... }

Import it into the application

@SpringBootApplication
@Import({ DataConfiguration.class })
public class MainApplication { ... } 

but don't import into MyControllerTest

Nikolai Shevchenko
  • 7,083
  • 8
  • 33
  • 42