Mockito Page<> test return null - spring

I'm testing controller using mockito. Even though I stubbed about the getBoardList, It doesn't initiate the method.
This is the controller. getBoardList() doesn't initiate when I checked in debug mode.
#GetMapping
public String getBoardListView(#Valid #Nullable BoardDto.Request request,
#PageableDefault(size = 10, sort = "createdAt", direction = Sort.Direction.ASC) Pageable pageable,
ModelMap map) {
Page<BoardDto.Response> boardList = postService.getBoardList(request, pageable);
map.addAttribute("boardList", boardList);
return "board/index";
}
This is the controllerTest
#MockBean private PostService postService;
#Test
void getBoardListView() throws Exception {
Page<BoardDto.Response> mock = Mockito.mock(Page.class);
when(postService.getBoardList(eq(null), any(Pageable.class))).thenReturn(mock);
mockMvc.perform(get("/board").with(csrf()))
.andExpect(status().isOk())
.andExpect(content().contentTypeCompatibleWith(MediaType.TEXT_HTML))
.andExpect(model().attributeExists("boardList"))
.andExpect(view().name("board/index"));
then(postService).should().getBoardList(any(BoardDto.Request.class), any(Pageable.class));
}
This is PostService interface.
public interface PostService {
Page<BoardDto.Response> getBoardList(BoardDto.Request request, Pageable pageable);
}
This is PostServiceImpl
#RequiredArgsConstructor
#Transactional(readOnly = true)
#Service
public class PostServiceImpl implements PostService {
private final PostRepository postRepository;
#Override
public Page<BoardDto.Response> getBoardList(BoardDto.Request request, Pageable pageable) {
return postRepository.findBoardList(request, pageable).map(BoardDto.Response::from);
}
}

Instead of:
when(postService.getBoardList(eq(null) ...
try:
when(postService.getBoardList(any(BoardDto.Request.class)

If you want to match a null argument, use ArgumentMatchers#isNull, not eq(null):
when(postService.getBoardList(isNull(), any(Pageable.class))).thenReturn(mock);

Related

Spring WebFluxTest add Pageable resolver

I want to test my Spring controller using #WebFluxTest(MyController.class)
My test :
#WebFluxTest({MyController.class})
class MyControllerTest {
#MockBean
private MyService myService;
#Autowired
private WebTestClient client;
#Test
void myTest() {
List<Integer> list = List.of(1,2,3);
Page<Integer> expected = new PageImpl<>(list);
String buCode = TestUtils.getRandomString();
when(myService.method(
any(), // Pageable
anyString()
)).thenReturn(Mono.just(expected));
client.get()
.uri("/path?arg=test")
.exchange()
.expectStatus()
.isOk();
}
}
My controller
#RestController
#RequestMapping("path")
#AllArgsConstructor
public class MyController {
private MyService myService;
#GetMapping
Mono<Page<Integer>> searchSeller(
Pageable pageable,
#RequestParam(required = false) String arg
) {
return myService.search(pageable, arg);
}
}
But I have this exception when I execute my test :
No primary or default constructor found for interface org.springframework.data.domain.Pageable
I think the solution is maybe to register the org.springframework.data.web.ReactivePageableHandlerMethodArgumentResolver but I don't know how to register it into the WebTestClient
Have you some clues to fix this issue ?

Test Result showing null while performing jUnit5 Test

I am writing a jUnit5 test to test my getUserByEmail(String email) using Mockito and when running the test, it is failing.
#SpringBootTest
#ExtendWith(MockitoExtension.class)
class UserServiceTest {
#MockBean
private UsersRepository userRepository;
#Autowired
private UserService userService;
#Test
void check_email_existInDB_thenReturn_True() {
// given - precondition or setup
UserDetails userdetails2 = new UserDetails(101L, "Anthony Ji", "anthony#gmail.com", "password2");
userRepository.save(userdetails2);
// when - action or behaviour that we are going test
when(userRepository.save(userdetails2)).thenReturn(userdetails2);
// then - verify the result or output using assert statements
assertEquals(userdetails2.getEmail(), userService.getUserByEmail("anthony#gmail.com"));
//assertTrue(userService.getUserByEmail(userdetails2.getEmail()));
}
}
This is my interface with extending of JPARepository
public interface UsersRepository extends JpaRepository<UserDetails, Long>{
}
This is my service level class
#Service
public interface UserService {
public Optional<UserDetails> getUserByEmail(String email);
public UserDetails saveUserDetails(UserDetails userDetails);
}
And this is the serviceImpl Class..
#Service
public class UserServiceImpl implements UserService{
#Autowired
private UsersRepository userRepository;
#Override
public Optional<UserDetails> getUserByEmail(String email) {
List<UserDetails> allUsers = this.userRepository.findAll();
Optional<UserDetails> userInfo = allUsers.stream().filter(user -> user.getEmail().equalsIgnoreCase(email)).findAny();
return userInfo;
}
#Override
public UserDetails saveUserDetails(UserDetails userDetails) {
UserDetails savedUserDetails = this.userRepository.save(userDetails);
return savedUserDetails;
}
}
and finally, this is my controller class while using jersey framework.
#Path(value = "/user")
public class RegistrationResources {
private static Logger logger = LoggerFactory.getLogger(RegistrationResources.class);
#Autowired
private UserService userService;
#POST
#Path("/registration")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public Response registerUser(UserDetails userDetails, #Context UriInfo uriInfo) {
logger.info("Inside the registration resource and registering the user");
boolean isEmailExists = isEmailExists(userDetails.getEmail());
if(isEmailExists) {
logger.info("Email Already Registered");
return Response.status(404).entity("Email Address already registered").build();
}
else {
this.userService.saveUserDetails(userDetails);
logger.info("User successfully registered");
return Response.status(200).entity("User successfully registered").build();
}
}
public boolean isEmailExists(String email) {
UserDetails userByEmail = this.userService.getUserByEmail(email).orElse(null);
if(userByEmail == null) {
return false;
}
return true;
}
I tried as above explained in the code.

How to mock Feign Client

I can't mock my Feign Client using Mockito.
MyService.class
#Service
#AllArgsConstructor
public class MyService implements IMyService{
private static final Logger LOGGER = LoggerFactory.getLogger(MyService .class);
private final MyRepository repository;
private final MyFeignClient myFeignClient;
#Autowired
private MyDao myDao;
#Override
#Async
public void process(Map<UUID, Long> command) {
DocIds docIds = getDocIds(command.values().stream().findFirst().get());
archiveData(command.keySet().stream().findFirst().get(), documentIds.getIds());
}
private DocumentIds getDocIds(Long retentionId) {
return myFeignClient.getDocumentIds(retentionId);
}
private void archiveData(UUID execId, List<Long> docIds) {
List<MyDocument> myDocs= prepareMyDocs(docIds);
repository.saveAll(myDocs);
}
And my test class:
#RunWith(SpringRunner.class)
#SpringBootTest
#ActiveProfiles("test")
public class ArchiveServiceTest {
#Autowired
ArchiveService archiveService;
#MockBean
MyDao myDao;
#MockBean
DocRepository archiveRepository;
#MockBean
private MyFeignClient myFeignClient;
#Test
public void shouldReturnTheSameNumberOfDocumentsToArchive() {
//given
List<DocData> documentData = prepareDocumentData();
// doReturn(new DocIds()).when(myFeignClient).getDocumentIds(1000L);
DocumentIds documentIds = new DocumentIds();
documentIds.setIds(Arrays.asList(1L, 2L));
when(myFeignClient.getDocIds(any())).thenReturn(documentIds);
when(documentDataDao.getAllDocumentData(anyList())).thenReturn(documentData);
doNothing().when(archiveRepository.saveAll(any()));
//when
Map<UUID, Long> command = new HashMap<>();
command.put(UUID.randomUUID(), 1000L);
archiveService.process(command);
//then
...
MyFeignClient:
#FeignClient(name = "myFeignClient", url = "${feign.searcher.path}")
public interface MyFeignClient{
#RequestMapping(method = RequestMethod.GET, path = "/document/path/{id}")
DocIds getDocumentIds(#PathVariable("id") Long id);
}
When running a test,
return myFeignClient.getDocumentIds(retentionId);
returns NULL. Why?
I don't have more ideas. I don't want to use WireMock. The same happens with my documentDataDao that doesn't return any values (null) specified in thenReturn() clause.
Have You tried it this way:
Mockito.when(myFeignClient.getDocumentIds(Mockito.eq(1000L))).thenReturn(new DocIds());
In You example, mock is commented out ;)
// doReturn(new DocIds()).when(myFeignClient).getDocumentIds(1000L);
But I'm sure it is just a bug in Your example.

Issue with Spring boot Controller with Mockito test case

I am completely new to Mockito and I have to write a test case for my REST Controller, but I am not sure where should I start. Any help would be really appreciated.I've updated my controller based on given suggestion.
Here's my controller:
#RestController
#RequestMapping("/api")
public class TestController {
#Autowired
TestService _testService;
#RequestMapping(value = "/getsearchDetailCourse", method = RequestMethod.GET)
public List<TestDto> getsearchDetailCourse(#RequestParam("courseName") String courseName,
#RequestParam("courseId") Long courseId) throws Exception {
return (List<TestDto>) _testService.searchDetailCourse(courseName, courseId);
}
}
My TestDto:
public class TestDto {
private String numberOfCourse;
private Long courseId;
public TestDto(){}
public TestDto(String numberOfCourse,Long courseId ){
super();
this.numberOfCourse = numberOfCourse;
this.courseId = courseId;
}
public String getNumberOfCourse() {
return numberOfCourse;
}
public void setNumberOfCourse(String numberOfCourse) {
this.numberOfCourse = numberOfCourse;
}
public Long getCourseId() {
return courseId;
}
public void setCourseId(Long courseId) {
this.courseId = courseId;
}
}
Here's my test:
#RunWith(SpringRunner.class)
#WebMvcTest(value = TestController.class, secure = false)
public class TestMethod {
#Autowired
private MockMvc mockMvc;
#MockBean
private TestService testService;
TestDto testDto = new testDto("Test",2744L);
#Test
public void retrieveDetailsForCourse() throws Exception {
Mockito.when(
testService.searchDetailCourse(Mockito.anyString(),
,Mockito.anyLong())).thenReturn(testDto);
RequestBuilder requestBuilder = MockMvcRequestBuilders.get(
"/api/getsearchDetailCourse").accept(
MediaType.APPLICATION_JSON);
MvcResult result = mockMvc.perform(requestBuilder).andReturn();
System.out.println(result.getResponse());
String expected = "[{\"numberOfCourse\":\"Testing1\",\"courseId\":2744},{\"numberOfCourse\":\"Testing2\",\"courseId\":2744}]";
JSONAssert.assertEquals(expected, result.getResponse()
.getContentAsString(), false);
}
}
I want to test the controller, please help me correct the test case above.

Spring controller testing with Mockito

I'm trying to test My Spring controllers using Mockito, but I can't actually get how can I do that without making everything #Mock.
Moreover test method returns me NullPointerException, as it can see no user and actually no user role at all.
Is there a way to test my controllers somehow?
(Controller class)
#Controller
#SessionAttributes("user")
#RequestMapping("/login.htm")
public class LoginController{
#Autowired
private UserDao userDao;
#Autowired
private LoginValidator loginValidator;
public LoginValidator getLoginValidator() {
return loginValidator;
}
public void setLoginValidator(LoginValidator loginValidator) {
this.loginValidator = loginValidator;
}
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
#RequestMapping(method = RequestMethod.GET)
public String getSendEmptyForm(ModelMap model, HttpServletRequest req) {
req.getSession().invalidate();
model.addAttribute("loginForm", new LoginForm());
return "login";
}
#RequestMapping(method = RequestMethod.POST)
public String postSubmittedForm(ModelMap model, #ModelAttribute("loginForm") LoginForm loginForm,
BindingResult result, SessionStatus status) {
//validate form
loginValidator.validate(loginForm, result);
if (result.hasErrors()) {
return "login";
}
User user = userDao.findByLogin(loginForm.getLogin());
model.addAttribute("user", user);
if (user.getRole().getName().equals("Admin")) {
model.addAttribute("usersList", userDao.findAll());
return "viewAllUsersPage";
}
if (user.getRole().getName().equals("User")){
return "userPage";
}
model.addAttribute("error", "Your role is not User or Admin");
return "errorPage";
}
}
And my testing class
#RunWith(MockitoJUnitRunner.class)
public class LoginControllerTest {
#InjectMocks
private LoginController controllerUT = new LoginController();
#Mock
private ModelMap model;
#Mock
private LoginForm loginForm;
#Mock
private BindingResult result;
#Mock
private SessionStatus status;
#Mock
private LoginValidator validator;
#Mock
private UserDao userDao;
#Mock
private User useк;
#Test
public void testSendRedirect(){
final String target = "login";
String nextPage = controllerUT.postSubmittedForm(model, loginForm, result, status);
assertEquals(target, nextPage);
}
}
First off you seem to be missing stubbing for loginForm.getLogin() and userDao.findByLogin(loginForm.getLogin()) and user.getRole().getName(). Without such stubbing, these methods called on a mock will return a default value (i.e. null).
So you may want to add :
when(loginForm.getLogin()).thenReturn(login);
when(userDao.findByLogin(login)).thenReturn(user);
when(user.getRole()).thenReturn(role);
when(role.getName()).thenReturn("Admin");
You will want to vary the return values for different tests.
Depending on your implementation classes for User and Role, you could simply supply real instances.
For a test that simulates the result to have errors you'll want to add this stubbing :
when(result.hasErrors()).thenReturn(true);
since otherwise the default false is returned.

Resources