3

I want to write a test for my BookService. This is that test. I don't know why I get the below error all the time:

org.junit.jupiter.api.extension.ParameterResolutionException: No ParameterResolver registered for parameter 
[com.mrfisherman.library.service.domain.BookService bookService] in constructor 
[public com.mrfisherman.library.service.domain.BookServiceTest(com.mrfisherman.library.service.domain.BookService,
com.mrfisherman.library.persistence.repository.BookRepository)].

As you can see I don't use parametrized tests here. Thank you in advance!

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Server.class)
class BookServiceTest {

    private final BookService bookService;
    private final BookRepository bookRepository;

    public BookServiceTest(BookService bookService, BookRepository bookRepository) {
        this.bookService = bookService;
        this.bookRepository = bookRepository;
    }

    @Test
    void saveBook() {
        //given
        Book book = new Book();
        book.setTitle("Book 1");
        book.setPublishYear(1990);
        book.setType(BookFormat.REAL);
        book.setIsbn("1234567890");
        book.setDescription("Very good book");
        book.setNumberOfPages(190);
        book.setSummary("Very short summary");
        book.setCategories(Set.of(new Category("horror"), new Category("drama")));

        //when
        bookService.saveBook(book);

        //then
        Optional<Book> loaded = bookRepository.findById(book.getId());
        assertThat(loaded).isPresent();

    }
}
Joris Schellekens
  • 8,483
  • 2
  • 23
  • 54
MrFisherman
  • 720
  • 1
  • 7
  • 27

3 Answers3

5

In JUnit Jupiter, a ParameterResolutionException is thrown whenever a test class constructor, lifecycle method (such as @BeforeEach), or test method declares a parameter that cannot be resolved by one of the registered ParameterResolver extensions.

Thus, a ParameterResolutionException can be thrown even when you are not using a @ParameterizedTest method.

When using @SpringBootTest, the SpringExtension is automatically registered for you. The SpringExtension implements the ParameterResolver extension API from JUnit Jupiter so that you can have beans from your ApplicationContext injected into constructors and methods in your test class.

The easiest way to solve your issue is to annotate the BookServiceTest constructor with @Autowired.

For more information and alternative approaches, check out the Dependency Injection with SpringExtension section of the Spring reference docs.

Sam Brannen
  • 29,611
  • 5
  • 104
  • 136
2

It is parameterized. How is the test framework supposed to create a new instance of the BookServiceTest class?

Ordinarily, test classes have a no-args constructor (at which point, the framework can just create a new instance without needing any additional information, such as 'how do I obtain an instance of bookService to pass to this constructor?').

rzwitserloot
  • 85,357
  • 5
  • 51
  • 72
  • So what I should do now, using @BeforeAll and there put BookService and BookRepository? – MrFisherman Jan 28 '21 at 09:59
  • MrFisherman is using Spring. Thus, the last comment is bad advice. In an integration test using Spring Boot, one would rather have the Spring-managed components injected into the test class instance -- for example using `@Autowired`. – Sam Brannen Jan 28 '21 at 14:37
  • 1
    @SamBrannen D'oh, yes, of course - I've deleted my comment (which suggested to use `@Before` method that initializes them). – rzwitserloot Jan 28 '21 at 15:07
0

That error happens on junit5 test with jboss Weld container initialization as well. If you don't have an additional annotation on test the @ParameterizedTest method fails. Pls use @ExplicitParamInjection to fix it.

@EnableWeld
@ExplicitParamInjection // that should be put to prevent error in test run
class MyCustomTest {

    @WeldSetup
    public WeldInitiator weld = WeldInitiator.from()...........build();

    @CsvSource(value = {1, 2, 3})
    @ParameterizedTest
    void getEventsByFilter(int inputValue) {
       // do some stuff with inputValue
    }
}

}

blandger
  • 718
  • 7
  • 17