1

Let's say I'm testing a repository :

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserRepositoryTest {
  @Test
  (...)
  @Test
  (...)
}

I'm ok that spring loads other repositories, but I'm not ok it loads the embedded Tomcat, the services, the controllers, ... every time I launch one of these JUnit.

What is the simplest way to achieve this?

I've tried to put some inner @Configuration class with a @ComponentScan limited to my repository package but it didn't work (it was just ignored).

Tristan
  • 8,733
  • 7
  • 48
  • 96
  • Just specify within the `classes` argument fo the `@SpringBootTest` annotation which classes it should use. This can either be a local Spring configuration, some `AutoConfiguration` you want to load or some service/component specified classes. – Roman Vottner Nov 22 '18 at 14:39
  • Well, I have some "configuration" classes for very specific things (security, database, swagger, ...) but I don't have config classes to group my beans, they are all scanned. And I don't have a config which tells Tomcat to start. What should I disable before going your way ? – Tristan Nov 22 '18 at 14:52
  • By default `@SpringBootTest` will not perform a `@ComponentScan` AFAIK. If no nested `@Configuration` class is available it will search its tree upwards for any and use this instead. You can, of course, always define some nested ones along the line `@Configuration static class Config { @Bean CustomService customService() { return mock(CustomService.class); } }` within your test class or try to [exclude classes from being component scanned](https://stackoverflow.com/questions/18992880/exclude-component-from-componentscan) – Roman Vottner Nov 22 '18 at 15:15
  • If you create a configuration in a test class itself, you should use `@TestConfiguration` annotation instead of `@Configuration` – Wim Deblauwe Nov 22 '18 at 16:22
  • `@TestConfiguration` is for additional config, @Configuration is to replace config, which is what I want. – Tristan Nov 22 '18 at 22:35

2 Answers2

4

Use the annotation @DataJpaTest instead of @SpringBootTest. It only loads the persistence related part of Spring.

@RunWith(SpringRunner.class)
@DataJpaTest
public class UserRepositoryTest {
  @Test
  (...)
  @Test
  (...)
}

You will find a detailed solution here

If you have some usage of JdbcTemplate then take a look to this answer

Lorelorelore
  • 3,335
  • 8
  • 29
  • 40
  • It's good to know. But not really an answer for all case. Right now, I'm using spring-jdbc. Also I may have some test with only 1 service dependency. – Tristan Nov 22 '18 at 14:49
  • Maybe it is better to clarify in the question that you are using `JdbcTemplate`. – Lorelorelore Nov 22 '18 at 15:09
  • But the question is not especially about the repository layer, this is just an example. Also, I've found "@JdbdTest", but it's still a very partial answer. – Tristan Nov 22 '18 at 15:15
1

It looks like there is not one single answer to this question.

Of course, for JPA repositories, Lore answer is the best : use @DataJpaTest (or @JdbcTest for my use case). But be also sure to use "@AutoConfigureTestDatabase(replace = Replace.NONE)" if your test data is in your database and not in some in-memory one.

Also there is a special chapter talking about this in Spring doc :

Spring Boot’s auto-configuration system works well for applications but can sometimes be a little too much for tests. It often helps to load only the parts of the configuration that are required to test a “slice” of your application.

source : https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html#boot-features-testing-spring-boot-applications-testing-autoconfigured-tests

But it doesn't show all you can/need to do.

For example, I had a smtpClientService to test.

To test this service, alone in its own layer, I had to do these specific adaptations (if I omit "@AutoConfigureWebClient", I won't get RestTemplateBuilder injected) :

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureWebClient
public class smtpClientServiceTest {

  @Autowired
  SmtpClientService service;

  @Configuration
  @Import(SmtpClientConfig.class)
  @ComponentScan(basePackageClasses = SmtpClientService.class)
  static class TestConfiguration {
  }  

  @Test
  public void testSendMessage() {
    (...)
  }

}
Tristan
  • 8,733
  • 7
  • 48
  • 96