I am trying to learn to test using Spring 5, Mockito, and JUnit 5. I have a small normal controller class and its test is as below:
@Controller
@RequestMapping("/customer")
public class CustomerController {
@Autowired
CustomerService customerService;
@Autowired
CustomerForm customerForm;
@GetMapping("/index")
public ModelAndView index(){
String customerName = customerService.getCustomerById(14).getFirstname(); <-- Giving me error here
customerForm.setCustomerName(customerName);
ModelAndView modelAndView = new ModelAndView("customer/pages/customer/Home");
modelAndView.addObject("customerForm", customerForm);
return modelAndView;
}
}
@ExtendWith(MockitoExtension.class)
class CustomerControllerTest {
@InjectMocks
CustomerController customerController;
@Mock
CustomerServiceImpl customerService;
@Mock
CustomerForm customerForm;
Customer customer;
String customerName;
@SuppressWarnings("deprecation")
@BeforeEach
void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
customer = new Customer(14, "John");
customerName = "John";
}
@Test
void testIndex() {
int customerId = 14;
when(customerService.getCustomerById(customerId).getFirstname()).thenReturn(customerName); <-- Giving me error here, NullPointerException
customerForm.setCustomerName(customerName);
ModelAndView mav = customerController.index();
assertEquals( customerForm, mav.getModel().get("customerForm"));
}
}
Error:
java.lang.NullPointerException
at com.primis.controller.CustomerControllerTest.testIndex(CustomerControllerTest.java:66)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:688)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
When I run this test, I am getting NullPointerException
as shown.
Please can someone point me in the right direction, what I am doing wrong.
Thank you
CodePudding user response:
You have to mock customerService.getCustomerById(customerId)
first, otherwise it will return null
and, in this case, throw NPE.
CodePudding user response:
You are mocking the wrong thing:
when(customerService.getCustomerById(customerId).getFirstname()).thenReturn(customerName);
What you actually need to mock is only the call customerService.getCustomerById()
. This means that your testing code should be something like:
@ExtendWith(MockitoExtension.class)
class CustomerControllerTest {
@InjectMocks
CustomerController customerController;
@Mock
CustomerServiceImpl customerService;
@Mock
CustomerForm customerForm;
Customer customer;
String customerName;
@SuppressWarnings("deprecation")
@BeforeEach
void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
customer = new Customer(14, "John");
customerName = "John";
}
@Test
void testIndex() {
int customerId = 14;
when(customerService.getCustomerById(customerId)).thenReturn(customer);
customerForm.setCustomerName(customerName);
ModelAndView mav = customerController.index();
assertEquals( customerForm, mav.getModel().get("customerForm"));
}
}
As a side note, I believe that with @ExtendWith(MockitoExtension.class)
you don't really need the explicit MockitoAnnotations.initMocks(this);
call.