I'm struggling with configuration for my @DataJpaTest. I'd like to take advantage of auto-configured spring context provided by @DataJpaTest, but I'd like to override some of it's beans.
This is my main class:
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Bean
public CommandLineRunner commandLineRunner(BookInputPort bookInputPort) {
return args -> {
bookInputPort.addNewBook(new BookDto("ABC", "DEF"));
bookInputPort.addNewBook(new BookDto("GHI", "JKL"));
bookInputPort.addNewBook(new BookDto("MNO", "PRS"));
};
}
As you can clearly see, I provide my implementation for CommandLineRunner that depends on some service.
I also have a test:
@DataJpaTest
public class BookRepositoryTest {
public static final String TITLE = "For whom the bell tolls";
public static final String AUTHOR = "Hemingway";
@Autowired
private BookRepository bookRepository;
@Test
public void testRepository() {
Book save = bookRepository.save(new Book(TITLE, AUTHOR));
assertEquals(TITLE, save.getTitle());
assertEquals(AUTHOR, save.getAuthor());
}
}
When I run the test I get the following error:
No qualifying bean of type 'com.example.demo.domain.book.ports.BookInputPort' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
That makes perfect sense! Auto-configured test provides implementation only for a 'slice' of the context. Apparently implementation of BookInputPort is missing. I do not need this commandLineRunner in a test context. I get create a commandLineRunner that does not depend on any service. I can try to solve the issue by adding to my test class nested class :
@TestConfiguration
static class BookRepositoryTestConfiguration {
@Bean
CommandLineRunner commandLineRunner() {
return args -> {
};
}
}
That solves the problem. Kind of. If I had more tests like this I would have to copy-paste this nested class to each test class. It's not an optimal solution.
I tried to externalize this to a configuration that could be imported by @Import
This is the config class:
@Configuration
public class MyTestConfiguration {
@Bean
public CommandLineRunner commandLineRunner() {
return args -> {
};
}
}
But then the application fails with a message:
Invalid bean definition with name 'commandLineRunner' defined in com.example.demo.DemoApplication: Cannot register bean definition
I checked that error and other folks on SO suggested in this case:
@DataJpaTest(properties = "spring.main.allow-bean-definition-overriding=true")
I did that and I got:
No qualifying bean of type 'com.example.demo.domain.book.ports.BookInputPort' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
That is exactly the same problem I started with. I took all these steps and found myself in the place where I was at the very beginning.
Do you have any idea how to solve this issue? I do not have a vague idea or clue.