26

In a SpringBoot application, I would like to do some test about the repository layer.

@RunWith(SpringRunner.class)
@DataJpaTest
public class VisitRepositoryTest {

     @Autowired
     private TestEntityManager entityManager;

     @Autowired
     private VisitRepository visitRepository;

     ...
}

When I try to run test from VisitRepositoryTest, I get an error about DefaultConfigService

Field defaultConfigService in com.norc.Application required a bean of type 'com.norc.service.DefaultConfigService' that could not be found.

So this needs to run the Application?

I tried to put a bean of DefaultConfigService in VisitRepositoryTest, but it's not allowed.

This class is used in my app

@EntityScan(basePackageClasses = {Application.class, Jsr310JpaConverters.class})
@SpringBootApplication
@EnableScheduling
public class Application implements SchedulingConfigurer {

      @Autowired
      private DefaultConfigService defaultConfigService;
      ...
}

How to manage that?


Edit

In my Application, I use this class in a cron tab:

@Service
public class DefaultConfigServiceImpl implements DefaultConfigService {

    private final DefaultConfigRepository defaultConfigRepository;

    @Autowired
    public DefaultConfigServiceImpl(final DefaultConfigRepository defaultConfigRepository) {
         this.defaultConfigRepository = defaultConfigRepository;
    }
}
nbro
  • 15,395
  • 32
  • 113
  • 196
robert trudel
  • 5,283
  • 17
  • 72
  • 124
  • I don't understand how Application wiring is coming as an issue during your testing run - it shouldn't be used at all. The error would make sense if you were trying to start the application via the Application class directly. Can you try adding @ComponentScan("com.norc") in your Application class. – dimitrisli Dec 11 '16 at 02:12
  • Actually, I just try to run VisitRepositoryTest... with you line... Application is starting... don't really understand why ... but that work – robert trudel Dec 11 '16 at 03:02
  • Did you manage to use `Jsr310JpaConverter` in your tests? – xenteros Jul 03 '18 at 18:22

1 Answers1

93

The problem is that your @SpringBootApplication has some additional configuration regarding scheduling and by adding that there and not having a custom @SpringBootConfiguration for your test, such scheduling requirement becomes mandatory for everything.

Let's take a step back. When you add @DataJpaTest, Spring Boot needs to know how to bootstrap your application context. It needs to find your entities and your repositories. Slice tests will recursively search for a @SpringBootConfiguration: first in the package of your actual test, then the parent, then the parent and if it doesn't find one it will throw an exception.

@SpringBootApplication is a @SpringBootConfiguration so if you don't do anything special, slice tests will use your app as the source for configuration (which is IMO, an excellent default).

Slice tests do not blindly start you app (otherwise that wouldn't be slicing) so what we do is disable auto-configuration and customize component scan for the task at hand (only scanning entities and repositories and ignoring all the rest when you use @DataJpaTest). That's a problem for you since the application configuration is applied and the scheduling stuff should be available. But dependent beans aren't scanned.

In your case, if you want to use slicing the scheduling configuration should move to a SchedulingConfiguration or something (it won't be scanned with slicing as explained above). Regardless, I think it's cleaner to separate a SchedulingConfigurer implementation anyway. If you do that, you'll notice the error will go away.

Let's assume now that you want for that particular test that FooService is also available. Rather than enabling component scan as dimitrisli suggested (that's basically disabling slicing for your configuration), you can just import the missing class

@RunWith(SpringRunner.class)
@DataJpaTest
@Import(FooService.class)
public class VisitRepositoryTest {
  ...
}
Stephane Nicoll
  • 31,977
  • 9
  • 97
  • 89
  • ok so i create another class only for scheduling. I use configuration and enablescheduling annotation. but i don't really understand what you mean by make that package protected configuration... – robert trudel Dec 12 '16 at 00:25
  • That was really a detail. You could have the scheduling configuration a "private thing" if you will in your code (`class SchedulingConfiguration` rather than `public class SchedulingConfiguration`). It doesn't change anything to my answer and was totally unrelated so I am going to edit and remove that. Sorry for the confusion – Stephane Nicoll Dec 12 '16 at 08:13
  • Is the `DataJpaTest` annotation to be used only for unit tests ? What then should be used for some integration tests ? Is test slicing supposed to be done only in unit tests ? – Stephane Jun 25 '18 at 13:47
  • 4
    Your import statement suggestion and explaination was perfect! Thank you! – Jordan Mackie Jun 28 '18 at 13:49
  • Excellent answer, many thanks. Would be even nicer if you can elaborate what would be the best way if, for instance, many classes would need to be added. Should one create a custom configuration class? How to 'import' many classes on that configuration? How should we 'import' that configuration to apply to our test? – Michiel Haisma Mar 15 '19 at 10:07