How can I handle UsernameNotFoundException? - java

I've been using some previous examples of testing methods some of my work partners used and they didn't have any problem but when i use them for this project it doesn't work at all. One of my partners saw the methods and he didn't know either what was wrong.
This is my test class:
#Mock
UserRepository dataRepository;
#Autowired
protected UserService userService;
private User u;
#BeforeEach()
void setUp() {
u = new User();
u.setId(23L);
u.setUsername("test");
u.setPassword("Pass1234.");
u.setInfo(null);
this.dataRepository.save(u);
}
#Test
void testLoadUserByUsername() throws Exception {
when(dataRepository.findByUsername(anyString())).thenReturn(u);
userService.loadUserByUsername("test");
assertEquals(u, userService.loadUserByUsername(anyString()));
verify(dataRepository).findByUsername(anyString());
}
#Test
void testFindAllUsers() throws Exception {
List<User> user = this.userService.findAllUsers();
Assertions.assertNotNull(user);
}
}
When i execute the test i get the same trace every time and it is, for the first method:
org.springframework.security.core.userdetails.UsernameNotFoundException: User can't be found
at com.project.UserService.loadUserByUsername(UserService.java:41)
I don't know what could it be because i'm searching the same name i'm setting just a few lines above so if u could help me i would appreciate it.
The UserService class is:
#Autowired
private BCryptPasswordEncoder passw;
#Autowired
private UserRepository userRepository;
#Autowired
private DataRepository dataRepository;
#Override
public UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException {
User user = this.userRepository.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("User can't be found");
}
return user;
}
public List<User> findAllUsers() {
List<User> l = new ArrayList<User>();
l = (List<User>) this.userRepository.findAll();
return l;
}
public void save(final User u) {
this.userRepository.save(u);
}
}
And the line of the code that is pointed by the exception is:
userService.loadUserByUsername("test");
Thank u so much.

the problem is with your #Mock. Basically, you are mocking an object in your test class and then pretending the #Autowired object in your UserService class to be mocked. What you are missing here is the instruction that tells Spring to put your mocked object into your UserService class. So here is the upgrade that will fix it.
Your test class becomes like this:
#Mock
UserRepository dataRepository;
#InjectMocks
#Autowired
protected UserService userService;
private User u;
#BeforeEach()
void setUp() {
u = new User();
u.setId(23L);
u.setUsername("test");
u.setPassword("Pass1234.");
u.setInfo(null);
this.dataRepository.save(u);
MockitoAnnotations.initMocks(this);
}
// Here goes the remaining code as it is...
Basically what I did was to add the #InjectMocks annotation above the #Autowired element that needs to receive your mock. Furthermore, with MockitoAnnotations.initMocks(this) I have initialized the mocks.
NOTE: the line where you do this.dataRepository.save(u); is useless. The point is that every method you call on a Mocked object is not executed, therefore there is no difference in having it or not. The only meaningful line is when(dataRepository.findByUsername(anyString())).thenReturn(u); that you have below.
PS. The dependency that contains #InjectMocks and MockitoAnnotations is the following:
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-all -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.8.4</version>
<scope>test</scope>
</dependency>
Wish you a great day,
D

Related

Mockito Junit 4 , Mock java method not getting called

I am trying to understand Mockito and Junit 4. I hava an interface named UserService which has a method named getUserInfo. I have written an implementation class UserServiceImpl to this interface.
I am using this getUserInfo method inside another class named UserInfoImpl. Now I am trying to Junit UserInfoImpl by Mocking UserServiceImpl. But instead of going to to the mock method, the call is going to the actual method. I have verified it by adding sysout to the actual method. I am not sure why it is not getting mocked. Can someone please throw some light.
Junit Class
public class Junit4WithMockito {
private UserInfoImpl userInfo;
#Mock
private UserService userService;
#Before
public void setUp() {
System.out.println("Inside Setup");
MockitoAnnotations.initMocks(this);
}
#Test
public void testUserInfoImpl() throws InterruptedException {
String cid="yu444";
userInfo = new UserInfoImpl();
userInfo.setUserService(userService);
when(userService.getUserInfo(cid)).thenReturn(new User("John Doe",33));
Assert.assertEquals("Peter",userInfo.getUserInfo(cid).getUsername());
}
}
UserInfoImpl Class
public class UserInfoImpl implements UserInfo {
private UserService userService;
public UserService getUserService() {
return userService;
}
public void setUserService(UserService userService) {
this.userService = userService;
}
#Override
public User getUserInfo(String username) {
try {
userService = new UserServiceImpl();
return userService.getUserInfo(username);
} catch (InterruptedException e) {
e.printStackTrace();
return null;
}
}
}
****** UserServiceImpl Class which I am trying to mock *********
public class UserServiceImpl implements UserService {
#Override
public User getUserInfo(String username) throws InterruptedException {
System.out.println("Inside the actual Service");
Thread.sleep(5000);
return new User("John Doe",33);
}
}
Error Message Below
You don't usually want to mock an implementation class, especially when there is an interface for it. The point of mocking is that you don't need (or want) the real implementation to be used.
So in your case, your #Mock should be
#Mock
private UserService userService;
Furthermore, you have this line in UserInfoImpl:
userService = new UserServiceImpl();
Obviously this replaces whatever instance of UserService you inject (including the mock). I'm guessing that's a mistake (maybe left around from an earlier attempt) since I can't think of any reason you'd really want to instantiate something that you're injecting.

while writing Junit test cases for #post method, i am getting null pointer exception at userService.addUser() mehod. could anyone help here

public class UserService {
#Autowired
private UserRepository userRepository;
#Autowired
private ConverterService converterService;
public User addUser(UserDto userdto) {
User convertedUser = converterService.convertToEntity(userdto);
convertedUser.setUserId(userdto.getUserId());
convertedUser.setUserName(userdto.getUserName());
User savedUser = userRepository.save(convertedUser);
return savedUser;
}
}
//while debugging userRepository.save(convertedUser) method, it always returning null.
Below is my UserServiceTest.java class
#RunWith(SpringRunner.class)
#SpringBootTest
public class UserServiceTest {
#Autowired
private UserService userService;
#Mock
private ConverterService converterService;
#MockBean
private UserRepository userRepository;
#Test
public void addUserTest() {
UserDto userDto = new UserDto();
userDto.setUserId("123");
userDto.setUserName("AB");
User user = new User("123","ABC");
Mockito.when(converterService.convertToEntity(new UserDto())).thenReturn(user);
Mockito.when(userRepository.save(user)).thenReturn(user);
User user1 = userService.addUser(userDto);
Assert.assertEquals(user,userService.addUser(userDto));
}
}
userService.addUser(userDto) this method is always return by null from service class. because of below condition is failing : Assert.assertEquals(user,userService.addUser(userDto));
you shouldn't pass null value to the assertEquals method. But you can do like this;
Assert.assertEquals(Objects.equals(user,userService.addUser(userDto)),true);

I am learning how to do the unit tests for the controllers and i don't know how to do it correctly

I'm learning how to test controllers and I still don't understand some things. I've watched some tutorials and I read some pages to learn but I don't understand 100%. I tried to do it but I don't think it's correct. I'm using Spring Boot and Mock.
This is my controller class:
#Autowired
private UserDetailsServiceImpl userService;
#Autowired
private ShopService shopService;
#Autowired
private GameService gameService;
#GetMapping(value = "/userProfile")
public String userProfile(final Model model, final HttpServletRequest request) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
Object principal = auth.getPrincipal();
User us = null;
if (principal instanceof User) {
us = (User) principal;
}
model.addAttribute("user", us);
model.addAttribute("teamsCreated", this.userService.teamsCreated(us));
model.addAttribute("teamshejoined", this.userService.teamsHeJoined(us));
model.addAttribute("gamesheplays", this.gameService.findGamesHePlays(us.getId()));
model.addAttribute("groupgamesheplays", this.gameService.findGroupHePlays(us));
model.addAttribute("prizehewon", this.gameService.getPrizeHeWon(us));
return "user/profile";
}
This is my test class:
#Autowired
private MockMvc mockMvc;
#MockBean
private UserDetailsServiceImpl userService;
#MockBean
private ShopService shopService;
#MockBean
private UserRepository userRepository;
#MockBean
private DataUserRepository dataUserRepository;
private User user;
private DataUser dataUser;
private Team team;
private Set<User> people;
#BeforeEach
void setUp() {
user = new User();
user.setId(12L);
user.setUsername("usertest");
user.setPassword("Pass1234");
dataUser.setId(915495L);
dataUser.setMoney(1);
dataUser.setUser(user);
user.setDataUser(dataUser);
people = new HashSet<>();
people.add(user);
team = new Team();
team.setId(2L);
team.setName("team1");
team.setCreator(user);
team.setPeople(people);
team.setCreationDate(Date.from(Instant.now()));
}
#WithMockUser(value = "spring")
#Test
void testProcessCreationUser() throws Exception{
mockMvc.perform(post("/userProfile")
.with(csrf())
.param("username", "usertest")
.param("password", "Pass1234")
.param("id", "49L")
.param("dataUser", ?????? )) // the ?? is because I dont know how to add a dataUser type, I only know Strings
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.view().name("users/createClienteForm"));
}
I tried doing it seeing previous methods some people made and with what I read before in notes I took, but i don't really understand so if you could tell me if that's correct or what is wrong and I could do better and I'd appreciate it. Thank you so much!
First of all, you're trying to mock a #GetMapping as a post() and it will not work.
Second, it seems that your resource does not need any parameter as it only gathers information about the user that is logged in your system, am I correct?
So, your test should look like:
#WithMockUser(value = "spring")
#Test
void testProcessCreationUser() throws Exception{
mockMvc.perform(get("/userProfile")
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.view().name("users/createClienteForm"));
}
You should review to which page your user will be redirected at the end, as
users/createClienteForm doesn't seem to be the corrected one in your mock.
Also, always choose a name for your test that correctly explains what your test is doing/verifying. I think testShowUserProfile should be fine in your case.

NullPointerException when testing service containing mocked JPA repository [duplicate]

This question already has answers here:
Why is my Spring #Autowired field null?
(21 answers)
Closed 2 years ago.
I am working on my first spring boot project and I am having trouble with testing my class as a Mockito newbie.
I need to check that the findAndUpdateUser method below update User entity fields correctly :
#Service
public class UserServiceImpl implements UserService {
#Autowired
private UserRepository userRepo;
public User findUser(String id) {
return userRepo.findById(id);
}
public User findAndUpdateUser(String id) {
User foundUser = findUser(id);
//some update on foundUser fields
return foundUser;
}
}
To test, I need to mock entity bean because I don't have DB locally. Here is my test class :
#RunWith(MockitoJUnitRunner.class)
public class UpdateFieldsTest {
#Mock
private UserRepository userRepo;
#Test
public void test1() {
User user = new User();
user.setId("testId");
//setting some other user fields
Mockito.when(userRepo.findById("testId")).thenReturn(user);
UserServiceImpl userService = new userServiceImpl();
User returnedUser = userService.findAndUpdateUser("testId");
//Checking if user field values are updated after findAndUpdate call
Assert.xxx
//other asserts
}
}
But this code throw me some NullPointerException on method call. I even tried to mock findUser method but I still have error...
Am I having a bad approach ? How should I test my method ?
Any help is welcomed
Thanks all
using this instantiation UserServiceImpl userService = new userServiceImpl(); make the UserRepo null;
you are using mockito, so you can use
#InjectMocks
private UserServiceImpl; and delete the instastiation line.
Mocks won't magicly appear inside of your object. You need to inject them manually. In you test, inside of the userService, the userRepo will be null. You inject dependancies either by constructor or by setter. It would look like this in your test:
UserServiceImpl userService = new userServiceImpl(userRepo);
Or
UserServiceImpl userService = new userServiceImpl();
userService.setUserRepo(userRepo);

JUnit test. The problem when converting entity to DTO by using ModelMapper library

I am working on the Spring Boot web app and I have a custom realization of the ModelMapper library that allows me to convert single objects and a list of objects.
#Component
public class ObjectMapperUtils {
#Autowired
private static ModelMapper modelMapper;
static {
modelMapper = new ModelMapper();
modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
}
private ObjectMapperUtils() {
}
public <D, T> D map(final T entity, Class<D> outClass) {
return modelMapper.map(entity, outClass);
}
public <D, T> List<D> mapAll(final Collection<T> entityList, Class<D> outCLass) {
return entityList.stream().map(entity -> map(entity, outCLass)).collect(Collectors.toList());
}
}
On the Service layer, I have a method returns from DB UserEntity object and convert it to UserDTO.
#Autowired
private UserRepository userRepository;
#Autowired
private ObjectMapperUtils modelMapper;
#Override
public UserDTO getByUserId(String userId) {
UserEntity userEntity = userRepository.findByUserId(userId)
.orElseThrow(() -> new NotFoundException("User with userId[" + userId + "] not found"));
//UserDTO userDTO = new UserDTO();
//BeanUtils.copyProperties(userEntity, userDTO);
return modelMapper.map(userEntity, UserDTO.class); // userDTO;
}
The problem occurs when I try to create a test for this method. UserDTO always returned as NULL value.
class UserServiceImplTest {
#InjectMocks
private UserServiceImpl userService;
#Mock
private UserRepository userRepository;
#Mock
private ObjectMapperUtils modelMapper;
#BeforeEach
void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
#Test
void testGetByUserId() {
UserEntity userEntity = new UserEntity();
userEntity.setId(1L);
userEntity.setUsername("zavada");
userEntity.setUserId("33b4c069-e907-45a9-8d49-2042044c56e0");
when(userRepository.findByUserId(anyString()))
.thenReturn(Optional.of(userEntity));
UserDTO userDTO = userService.getByUserId("33b4c069-e907-45a9-8d49-2042044c56e0");
System.out.println(userDTO); <--- NULL
assertEquals("zavada", userDTO.getUsername());
assertNotNull(userDTO);
}
}
When I use on the Service layer converting by BeanUtils.copyProperties(obj1, obj2); - the test is passed successfully. With ModelMapper I get NULL. Any ideas how to solve this error or refactor code? Thanks in advance
To build upon user268396 answer you would need the following to get this to work:
#RunWith(MockitoJUnitRunner.class)
public class StackOverflowTest {
#InjectMocks
private StackOverflow userService = new StackOverflow();
#Mock
private UserRepository userRepository;
#Mock
private ObjectMapperUtils modelMapper;
private UserDTO userDTO = new UserDTO();
private UserEntity userEntity = new UserEntity();
#Before
public void setUp() {
when(modelMapper.map(any(), any())).thenReturn(userDTO);
userDTO.setId(1L);
userDTO.setUsername("zavada");
userDTO.setUserId("33b4c069-e907-45a9-8d49-2042044c56e0");
}
#Test
public void testGetByUserId() throws Throwable {
when(userRepository.findByUserId(anyString())).thenReturn(Optional.of(userEntity));
UserDTO result = userService.getByUserId("33b4c069-e907-45a9-8d49-2042044c56e0");
System.out.println(result);
assertEquals("zavada", result.getUsername());
assertNotNull(result);
}
}
This is quite an easy mistake to make, it is important to remember that all you #mocked objects are not real implementations anymore and if you expect any behaviour back you would need to define it upfront.
If you have a #Mock private ObjectMapperUtils modelMapper; then by default you do not have a real ObjectMapperUtils. So you are not calling your implementation, you are calling the default stubs that Mockito provides for you. That is why you are getting a null return value from modelMapper.map().
Either do not mock the ObjectMapperUtils bean or arrange for it to do something suitable using when() etc. from the Mockito API.
For the same situation, you could also do
Do not mock the ObjectMapperUtils class in your test class.
In the #Before init() ..{} method instantiate your UserServiceImpl to new instance of ObjectMapperUtils. And then set it in the UserServiceImpl. i.e ,
userServiceImpl.setMapper(UserServiceImpl).
So your setup method will look something like this ,
#InjectMocks
private UserServiceImple userServiceImpl;
#Mock
private UserRepository userRepository;
private ObjectMapperUtil objectMapperUitl; // not mocked
#BeforeEach
public void init() {
objectMapperUitls = new ObjectMapperUtils();
userServiceImple.setMapper(objectMapperUitls);
}

Categories

Resources