I am running Junit Test cases which is throwning NullPointerException Here is my Junit Test Class Structure
#RunWith(SpringJUnit4ClassRunner.class)
public class EmployeeTest {
#InjectMocks
EmployeeRepository empRepo;
#InjectMocks
EmployeeService empService;
#Mock
EntityManager entityManager;
List<Employee> empList=new ArrayList<Employee>();
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
#Test
public void getEmployyeList(){
Employee e = new Employee(111,'Raunak','kumar','Hero Inc');
List<Employee> empList=empService.getAllEmployee();
Employee e1 = empList.stream().filter(emp->emp.getEmpId()==111).findAny().get();
assertEquals(e,e1);
}
}
And On the EmployeeService i am using EntityManager looks like
public class EmployeeService{
#Autowired
EntityManager em;
public List<Employee> getAllEmployee(){
return em.createNativeQuery("select e.* from employee e").getResultList();
}
}
When i am debugging the code found that em.createNativeQuery("select e.* from employee e") returns null. From the Rest API its working fine.
tried with
when(empRepo.findAll()).thenReturn(empList);
assertThat(users, containsInAnyOrder(
hasProperty("lastName", is("Kumar"))
));
But empRepo.findAll() also return []
you have to stub mock entity manager using mockito's when and thenReturn in your test case (getEmployyeList) like below , this should resolve NPE
#Test
public void getEmployyeList(){
Employee e = new Employee(111,'Raunak','kumar','Hero Inc');
Query query = mock(Query.class);
when(entityManager.createNativeQuery(anyString())).thenReturn(query);
doReturn(Arrays.asList(e)).when(query).getResultList();
List<Employee> empList=empService.getAllEmployee();
Employee e1 = empList.stream().filter(emp->emp.getEmpId()==111).findAny().get();
assertEquals(e,e1);
}
Related
I am creating test cases, in one of my service class method I am using mapStruct to map entity into dto class.
This is my mapper class
#Mapper(componentModel = "spring")
public interface UserMapper {
List<UserDto> toUserDto(List<UserEntity> users);
}
below is how I am injecting in my service class
#Service
#RequiredArgsConstructor
public class UserServiceImpl implements UserService{
private final UserMapper userMapper;
This is how I am using it
List<UserDto> userDto = userMapper.toUserDto(lst);
this is how I am doing it in my Test class
#RunWith(MockitoJUnitRunner.class)
#SpringBootTest(classes = Application.class)
public class ApplicationTest {
#Mock
private UserRepository userRepo;
#Mock
private UserMapper userMapper;
#InjectMocks
private UserServiceImpl userServiceImpl;
#Test
public void contextLoads() {
then(controller).isNotNull();
then(userServiceImpl).isNotNull();
}
#Test
public void getAllUser() {
List<UserEntity> lst = new ArrayList<UserEntity>();
UserEntity userOne = new UserEntity();
userOne.setEmpFullname("Test Test1");
userOne.setUserId("marina");
userOne.setFlag("Y");
UserEntity usertwo = new UserEntity();
usertwo.setEmpFullname("Test Test2");
usertwo.setUserId("test");
usertwo.setFlag("Y");
lst.add(userOne);
lst.add(usertwo);
when(userRepo.findByStatus("W")).thenReturn(lst);
try {
List<UserDto> pendingUsersList = userServiceImpl.getPendingUser();
assertEquals(2, pendingUsersList.size());
} catch (GeneralException e) {
e.printStackTrace();
}
}
}
when I am running my test cases I am able to see these 2 records in entity class but when this line executes
List<UserDto> userDto = userMapper.toUserDto(lst); it gives me blank array.
Note - In my entity Class I have many fields but from test class I am passing only 3 parameters.
You have annotated your UserMapper with a #Mock annotation, without writing the mockito configuration for this mock. Then the blank array is expected.
Remove the #Mock annotation, or specify what should be returned by the mock.
For example :
#RunWith(MockitoJUnitRunner.class)
#SpringBootTest(classes = Application.class)
public class ApplicationTest {
#Mock
private UserRepository userRepo;
#Spy
private UserMapper userMapper = Mappers.getMapper(UserMapper.class);
#InjectMocks
private UserServiceImpl userServiceImpl;
So I have this class (used lombok):
#RequiredArgsConstructor
#Service
public class ServiceImpl {
private final BookService bookService;
#Autowired
private TableService tableService;
public void method() {
if (!bookService.isEmpty()) return;
Object table = tableService.getObject();
}
}
My test class:
#ExtendWith(MockitoExtension.class)
#RunWith(JUnitPlatform.class)
public class ServiceImplTest {
#Mock BookService bookService;
#Mock TableService tableService;
#InjectMocks ServiceImpl serviceImpl;
#Test
public void testMethod() {
when(bookService.isEmpty()).thenReturn(true);
when(tableService.isEmpty()).thenReturn(new Object());
serviceImpl.method();
}
}
If I run it, the bookService is null. It is not injected in the class. When the code is at the if (!bookService.isEmpty()) return; the bookService is null.
if I change my testMethod to this:
#Test
public void testMethod() {
MockitoAnnotations.initMocks(this);
when(bookService.isEmpty()).thenReturn(true);
when(tableService.isEmpty()).thenReturn(new Object());
serviceImpl.method();
}
So I added MockitoAnnotations.initMocks(this); then the code Object table = tableService.getObject(); in my class returns null. So the tableService is not null, but the getObject() return null;
Any idea how to fix it? I am not let to change the class code.
Thanks in advance.
I have a UserDAO that has methods like add,delete,update,getUser and getUsers (to manipulate my database). I also have a Requestmapping that I want to test via Mockito. Here is everything relevant in terms of what I have:
The test:
#RunWith(SpringJUnit4ClassRunner.class)
#WebMvcTest(value = UserController.class)
public class UserControllerTest
{
#Autowired
private MockMvc mockMvc;
#Mock
private UserDAO userDao;
#InjectMocks
private UserController userController;
#Before
public void setUp()
{
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders
.standaloneSetup(userController)
.build();
}
#Test
public void testGetAllUsersSuccess() throws Exception{
User s = new User();
List<User> users = Arrays.asList(
new User(1,"somebody", "pass", "somebody#yahoo.com"),
new User(2, "sam", "mypass", "tom#hotmail.com"));
doReturn(users).when(userDao).getUsers();
mockMvc.perform(get("/userList"))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
.andExpect(jsonPath("$", hasSize(2)))
.andExpect(jsonPath("$[0].userID", is(1)))
.andExpect(jsonPath("$[0].name", is("somebody")))
.andExpect(jsonPath("$[0].password", is("pass")))
.andExpect(jsonPath("$[0].email", is("somebody#yahoo.com")))
.andExpect(jsonPath("$[1].userID", is(2)))
.andExpect(jsonPath("$[1].name", is("sam")))
.andExpect(jsonPath("$[1].password", is("mypass")))
.andExpect(jsonPath("$[1].email", is("tom#hotmail.com")));
verify(userDao, times(1)).getUsers();
verifyNoMoreInteractions(userDao);
}
}
UserController where I have my requestmapping:
#RestController
public class UserController {
/**
*
*
* #return list of all users
*/
#RequestMapping(value = "/userList", method = RequestMethod.GET)
public List<User> user() throws Exception {
UserDAO gettingUsers = new UserDAO();
return gettingUsers.getUsers();
}
}
the getUsers() method:
public List<User> getUsers(){
try(Session session = HibernateUtil.getSessionFactory().openSession()){
return session.createQuery("from User", User.class).getResultList();
}
}
PROBLEM: When I execute my test, a connection is made with the database (which is not what I want) instead of a fake instance of UserDAO that only returns the users list that I have made in mockito.
QUESTION: What should my code look like to be able to mock the userDAO method getUsers() such that it doesn't return the users from the database but instead returns the faked users list when I call it by requesting the get method of "/userList"?
UPDATE=
SOLUTION:
My new Controller:
#RestController
public class UserController {
private UserDAO userDAO;
public UserController (UserDAO userDAO)
{
this.userDAO = userDAO;
}
/**
*
*
* #return list of all users
*/
#GetMapping(value = "/Users", method = RequestMethod.GET)
public List<User> users() throws Exception {
return userDAO.getUsers();
}
}
Changes done in test:
//...
#MockBean
private UserDAO userDao;
....
when(userDao.getUsers()).thenReturn(users);
...//
Spring didn't find my userDAO Bean so I added the package name where I stored the bean in the ApplicationConfiguration class of mine. Doing this, Spring was able to inject the bean in the constructor.
The userDao mock is never set to the controller under test.
1) You don't want to use new to instantiate the UserDAO in your Controller :
UserDAO gettingUsers = new UserDAO();
You want to inject it as a Spring Bean.
Besides you also have to make the dependency visible because actually it is not settable from the unit test POV.
You could inject it in the constructor :
private UserDAO userDAO;
public UserController (UserDAO userDAO){
this.userDAO = userDAO;
}
2) You mock Spring bean in a running container with #MockBean from Spring Boot test not with #Mock from Mockito.
I want to InjectMocks into my interface and not my service class , so far its not possible with Mockito (I am using Mockito 2.8.9). I have used SpringBoot and using #MockBean I am able to test interfaces of services but with #Mock of SpringMvc I can only test a concrete class, why and what can I do to test services?
Any suggestion on how to get this to interface level.
#RunWith(MockitoJUnitRunner.class)
#ContextConfiguration(classes = EmployeeServiceImpl.class)
public class EmployeeServiceTest {
#org.mockito.Mock
private EmployeeDao employeeDao;
#InjectMocks
private EmployeeServiceImpl employeeService ;
#Before
public void initMocks() {
MockitoAnnotations.initMocks(this);
}
#Test
public void SaveEmployee() throws Exception {
Employee employee = new Employee();
employee.setEmployeeName("valentine");
employee.setSalary(400);
employee.setDepartmentId(1);
employee.setEmployeeId(1);
Employee employee1 ;
when(employeeDao.addEmployee(employee)).thenReturn(employee);
employee1 = employeeService.saveEmployee(employee);
org.junit.Assert.assertNotNull(employee);
assertEquals(employee1.getSalary(), employee.getSalary());
Mockito.verify(employeeDao).addEmployee(employee);
}
So i solved this by first creating Bean in Config class that returns interface of Dao
#Profile("test")
#Configuration
public class Config {
#Bean
#Primary
public EmployeeDao employeeDao(){
return Mockito.mock(EmployeeDao.class);
}
}
Then i used the profile in my test and set configContxt TO my Config Class
#ActiveProfiles("test")
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes ={ EmployeeServiceImpl.class, Config.class})
public class EmployeeServiceTest1 {
#Autowired
private EmployeeDao employeeDao;
#Autowired
private EmployeeService employeeService;
Mocked object not getting in service Here is my below code
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classesExternalProviderMain.class)
#ActiveProfiles(ApplicationConstants.DEVELOPMENT_PROFILE)
#WebAppConfiguration
public class EmployeeServiceTest {
#InjectMocks
EmployeeService employeeService;
#Mock
EmployeeRepository employeeRepository;
String name;
#Before
public void init() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testEmployee() {
Mockito.when(employeeRepository.findByName(name)).thenReturn(getEmployee());
List<Employee> resultedEmployees = employeeService.getEmployeeByName("mike");
}
private List<Employee> getEmployee(){
//here is the logic to return List<Employees>
}
}
public EmployeeServiceImpl implements EmployeeService{
#Autowired
EmployeeRepository employeeRepository;
employeeService.
public List<Employee> getEmployeeByName(String name){
List<Employee> employees = employeeRepository.findByName(name);
//Here I does't want to hit the real database so I have mocked it in testcase but I am getting empty list when I debug it. So can you please tell me what i did wrong in my "EmployeeServiceTest" to get List<Employee>
}
}
So is there any additional logic required in testcase to get the mocked object.
The problem is you are not mocking the call
employeeRepository.findByName("mike")
but you are mocking
employeeRepository.findByName(null)
since your variable name was never initialized. Change your code to:
Mockito.when(employeeRepository.findByName("mike")).thenReturn(getEmployee());