I was practicing Junit5 with Mockito and doing parameterized testing on spring boot application Postman request and responses tests show no issues with my code, but I could not accomplish with a junit5 test. I get " InvoicationTargetException " whenever I do MockMvc perform(..) method call. I have googled for possible solutions but I did not find what I was looking. Initially, I was having issue cause I was not mocking the service, but and this problem started showing up. I find it difficult to debug the test with breakpoints, and sometimes debugging does not step in to a method call, and difficult to understand the problem.
I could not recreate another scenario also where MockMvc .perform task gets completed, but MvcResult would be empty, and I get an error "Unparsable json string" . I do appreciate some directions on running the following junit test successfully.
Entity
Book : id(Integer), title(String),pubYear(String), author(Author)
Author : id(Integer), firstName(String), lastName(String), books(List)
AuthorRepository
@Repository
public interface AuthorRepository
extends CrudRepository<Author, Integer>{
@Query("select b from Author b where b.firstName= ?1 and b.lastName = ?2")
public Author findAuthorByName(String firstName, String lastName);
}
AuthorController
@RestController
@RequestMapping(value="/authors")
public class AuthorController {
@Autowired
private AuthorService authorService;
..................
@GetMapping(path = "/books/{first}/{last}")
public Book getBooksByAuthorName(@PathVariable String first, @PathVariable String last) {
Book book = this.authorService.getBooksByAuthorName(first, last);
return book;
}
}
AuthorService
@Service
public class AuthorService {
@Autowired
private AuthorRepository authorRepository;
@Autowired
private BookService bookService;
.................
public Book getBookByAuthorName(String first, String last) {
Author author = this.authorRepository.findAuthorByName(first, last);
Book b = author.getBooks().get(0);
return b;
}
AuthorControllerTest
@AutoConfigureMockMvc
public class AuthorControllerTest {
@Autowired
private MockMvc mockMvc;
@Mock
private AuthorService authorService;
//input for parameterized testing, currently only one test sample
public static Collection<Object[]> input() {
return Arrays.asList(new Object[][] {
{"Test-1",
"John",
"Banville",
"{ \"id\":1, \"title\":\"Eclipse\", \"pubYear\":\"2000\", \"author\":{\"id\":1, \"firstName\":\"john\", \"lastName\":\"banville\"}}"
}
});
}
@BeforeEach
public void initMOcks() {
MockitoAnnotations.initMocks(this);
}
@ParameterizedTest
@MethodSource("input")
public void testGetBooksByAuthor(String testId, String firstName, String lastName,
String expectedResponse) throws Exception {
ObjectMapper mapper = new ObjectMapper();
Book book = null;
if(expectedResponse != null) {
book = mapper.readValue(expectedResponse, Book.class);
}
doReturn(book).when(authorService).getBookByAuthorName(firstName,lastName);
MvcResult result = mockMvc.perform(
MockMvcRequestBuilders.get("/authors/books/{first}/{last}", firstName,lastName))
.andReturn();
System.out.println(testId + "Result: " + result.getResponse().getContentAsString());
System.out.println(testId + "Expect: " + expectedResponse );
JSONAssert.assertEquals(expectedResponse, result.getResponse().getContentAsString(), true);
}
}
As @Kathrin Geilmann suggested I added @MockBean. I have [read][1] this is not mocking, but I tried that I got
.UnsatisfiedDependencyException: Error creating bean with name 'authorController': Unsatisfied dependency expressed through constructor parameter 0; nested exception
then I added @MockBean for each nested dependencies. Below the arrow direction shows where those dependency beans are injected in the constructors in the classes I have.
AuthorController <-- AuthorService <-- (AuthorRepository, BookService)<-- Bookrepository
@MockBean
private AuthorService authorService;
@MockBean
private AuthorRepository authorRepository;
@MockBean
private BookService bookService;
Why BookReqpository is not considered "Unsatisfied dependency" ? I run the test I get
NullInsteadOfMockException, Argument passed to when() is null;
This is the line of the code from original post
doReturn(book).when(authorService).getBooksByAuthorName(firstName,lastName);
This is where I switched @MockBean to @Mock for authorService but I got the same error. So I switched back to @MockBean I have finally changed the test class annotation to use @WebMvcTest. This made the test run without any issue, and I also removed @AutoConfigureMockMvc did not create any problem.
@WebMvcTest
public class AuthorControllerTest {
Though I can run the test now, but I do not think I done any mocking, and I have read that @MockBean is not mocking. [1]: https://www.baeldung.com/java-spring-mockito-mock-mockbean
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.