Getting NullPointerException in Junit Test cases for an object [duplicate] - java

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 3 years ago.
I am new to Java, tried various ways to resolve this but there is no luck.
The TestFeedService interface object (testService) value is showing null on testService.sendMessage(dataBO, false) call. This is there inside the method I'm calling from the test case. I am not sure why this is happening. I tried creating Object in the setup() but still it is failing. Can someone please help me in this.
Below is the Test case code
public class testApiControllerTest {
private MockMvc mockMvc;
private TesApiController testApiController;
private TestFeedService testService;
#Before
public void setup() {
testApiController = mock(TestApiController.class);
testService = mock(TestFeedService.class);
testService = new TestFeedServiceImpl();
}
#Test
public void testProcessMessage() {
TestApiController testApiController = new TestApiController();
TestForm2 testForm2 = new TestForm2();
testForm2.setType("PROMO_CODE");
testForm2.setUserId("1");
testForm2.setMessage("Welcome");
ResponseEntity<?> responseEntity = testApiController.processMessage(testForm2);
assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
}}
Java Code:
public class TestApiController {
#Autowired
private TestFeedService testService; // This is an interface
#RequestMapping(path = "/api/process-message", method = RequestMethod.POST)
public ResponseEntity<?> processMessage(#RequestBody TestForm2 testForm) {
DataBO dataBO = convertBO(testForm);
testService.sendMessage(dataBO, false); // here I am getting testService = null and causing exception
return ResponseEntity.ok().build();
} // Some more code

You need to put the TestService in the constructor of TestApiController, so you can inject it when creating the object in the test.
public class TestApiController {
private TestFeedService testService; // This is an interface
#Autowired
public TestApiController(TestFeedService testService ) {
this.testService = testService;
}
#RequestMapping(path = "/api/process-message", method = RequestMethod.POST)
public ResponseEntity<?> processMessage(#RequestBody TestForm2 testForm) {
DataBO dataBO = convertBO(testForm);
testService.sendMessage(dataBO, false); // here I am getting testService = null and causing exception
return ResponseEntity.ok().build();
} // Some more code
So your test would be like:
public class testApiControllerTest {
private MockMvc mockMvc;
private TesApiController testApiController;
private TestFeedService testService;
#Before
public void setup() {
this.testService = mock(TestFeedService.class);
}
#Test
public void testProcessMessage() {
this.testApiController = new TestApiController(this.testService);
// More code
}}
Hope it helps

Related

How to mock service in service test?

I try write service test, for example, I have this ExamServiceImpl:
#Service
public class ExamServiceImpl implements ExamService {
#Autowired
private final SubjectService subjectService;
private final ScoreDAO scoreDAO;
#Autowired
public ExamServiceImpl(ScoreDAO scoreDAO) {
this.scoreDAO = scoreDAO;
}
#Override
public ResponseModel insertScore(RequestModel request) throws IOException {
List<TeacherModel> teacher = teacherDAO.getNameList(request);
List<StudentModel> student = studentDAO.findStudentList(teacher.get(0).getName, request.getStudentScore);
String nameStudent = student.get(0).getFirstName() + student.get(0).getLastName();
SubjectModel subject = subjectService.getNameSubject(request, nameStudent);
ScoreModel score = new ScoreModel();
score.setStudentName(request.getStudentName);
score.setScore(request.getStudentScore);
score.setSubject(subject.getName);
int result = scoreDAO.insert(score);
return result;
}
}
Sample my test:
#SpringBootTest
public class ExamServiceImplTest {
#MockBean
private ScoreDAO scoreDAO;
#Autowired
private SubjectService subjectService;
#Autowired
private ExamService examService;
#Test
void insertScoreTest() {
SubjectModel resFromSubject = new SubjectModel();
resFromSubject.setSubject("Math");
TeacherModel resTeacher = new Teacher()
resTeacher.setName("test Teacher");
StudentModel studentData = new Student();
student.setFirstName("firstname");
studebt.setLastName("lastname");
Mockito.when(teacherDAO.getNameList(new RequestModel())).thenReturn(resTeacher);
Mockito.when(studentDAO.findStudentList(anyString(), anyString())).thenReturn(studentData);
Mockito.when(subjectService.getNameSubject(Mokito.any(RequestModel.class), anyString())).thenReturn(resFromSubject);
Mockito.when(scoreDAO.insert(Mokito.any(ScoreModel.class)).thenReturn(1);
int resultTest = examService.insertScore(new RequestModel());
assertSame(ex, 1);
}
But output resultTest is error. I try debugger, I found
Mock studentDAO.findStudentList() return null >> mock is not working.
When I close code + test teacherDAO and studentDAO for test mock subjectService >> mock subjectService is not working too. (I not sure mock service should be use #Autowired or #MorkBean)
Please, could you help write me test methods? I covered with tests more simple other services.
Thank you!
You can find demo application in this blog
[https://blog.joshsoftware.com/2020/05/27/introduction-to-mockito-unit-testing-framework/][1]

How to mock FormFactory object in playframework 2.8 with java?

I want to write a unit test for a controller that uses a FormFactory object
My controller:
public class LoginController extends ApiController {
private final FormFactory formFactory;
#Inject
public LoginController(FormFactory formFactory) {
this.formFactory = formFactory;
}
public Result login(Http.Request request) {
DynamicForm form = formFactory.form().bindFromRequest(request);
String username = form.get("username");
String password = form.get("password");
doSomething();
return result;
}
}
In my test class I'll have to mock the external dependency FormFactory and to stub .form() and .bindFromRequest(request) as well, but I don't know how.
My test class is:
public class LoginControllerTest {
#InjectMocks
private LoginController controller;
#Mock
private FormFactory formFactory;
#Before
public void setup() {
MockitoAnnotations.openMocks(this);
}
#Test
public void login_ok() {
Map<String, String> formData = new HashMap<>();
formData.put("username", "user");
formData.put("password", "pass");
Http.RequestBuilder fakeRequest = new Http.RequestBuilder().method(Helpers.POST).bodyForm(formData);
when(formFactory.form()).thenReturn(new DynamicForm(???));
Result result = controller.adminLogin(fakeRequest.build());
}
}
If I test my class I got a NPE because .form() is null in LoginController class.
How Can I solve this issue?
What parameters I have to pass in new DynamicForm(???)?

MockBean is strange in restful services

I've made rest controller, that calls #service class:
#Service
public class UnitServiceImpl extends HttpRequestServiceImpl implements UnitService {
#Override
public Unit addUnit(String unitName) {
final Unit unit = new Unit();
unit.setUnitName(unitName);
return unitRepository.save(unit);
}
#Override
public Unit getUnit(int id) {
final Unit unit = unitRepository.findById(id);
if (unit == null) {
throw new EntityNotFoundException("Unit is not found");
}
return unit;
}
#Override
public Iterable<Unit> getAllUnits() {
return unitRepository.findAll();
}
}
EnityNotFoundException is handled by ExceptionHandlingController:
#RestController
#ControllerAdvice
public class ExceptionHandlingController extends ResponseEntityExceptionHandler {
#ExceptionHandler({RuntimeException.class})
public final ResponseEntity<ErrorDetails> handleRuntimeException(RuntimeException ex, WebRequest request) {
ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(),
request.getDescription(false));
HttpStatus httpStatus = HttpStatus.BAD_REQUEST;
if (ex.getClass() == EntityNotFoundException.class) {
httpStatus = HttpStatus.NOT_FOUND;
}
return new ResponseEntity<>(errorDetails, httpStatus);
}
}
Unit controller just calls the getUnit:
#RestController
public class UnitController {
private final UnitService managementService;
#PostMapping(value = "/unit", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Unit> addUnit(HttpServletRequest request) throws FieldsIsAbsentException {
final String unitName = managementService.getParameter(request, "unit_name");
final Unit unit = managementService.addUnit(unitName);
return new ResponseEntity<>(unit, HttpStatus.CREATED);
}
public UnitController(UnitService managementService) {
this.managementService = managementService;
}
#GetMapping(value = "/unit", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Iterable<Unit>> getAllUnits() {
final Iterable<Unit> allUnits = managementService.getAllUnits();
return new ResponseEntity<>(allUnits, HttpStatus.OK);
}
#GetMapping(value = "/unit/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Unit> getUnitById(#PathVariable("id") int id) {
final Unit unit = managementService.getUnit(id);
return new ResponseEntity<>(unit, HttpStatus.CREATED);
}
}
Now I need to test them, and created unit test method, that must to check on 404 error:
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#ContextConfiguration
class UnitControllerTest {
#Autowired
private MockMvc mockMvc;
#MockBean
UnitService unitService;
#MockBean
UnitRepository unitRepository;
#Autowired
private UnitController unitController;
private List<Unit> units;
#Before
public void initUnits() {
units = new ArrayList<>();
Unit unitWithName = new Unit();
unitWithName.setId(1);
unitWithName.setUnitName("NameUnit");
units.add(unitWithName);
Unit unitWithoutName = new Unit();
unitWithoutName.setId(2);
units.add(unitWithoutName);
}
#Test
void contextLoads() {
Assert.assertNotNull(unitController);
}
#Test
void testGetAllUnits() throws Exception {
given(this.unitService.getAllUnits()).willReturn(units);
mockMvc.perform(get("/unit"))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON));
}
#Test
void testUnitNotFound() throws Exception {
int id = -1;
given(this.unitRepository.findById(id)).willReturn(null);
mockMvc.perform(get("/unit/-1"))
.andExpect(status().isNotFound())
.andExpect(content().contentType(MediaType.APPLICATION_JSON));
}
}
When I run tests, testGetAllUnits fails:
java.lang.AssertionError: Content type not set
and testUnitNotFound fails with error:
java.lang.AssertionError: Status expected:<404> but was:<201>
But when I remove
#MockBean
UnitService unitService;
It will be working. What the problem?
UPDATE:
I have the similar problem now. This code inserts into database info about unit. But I made mock for the method.
#Test
void testAddUnit() throws Exception {
Unit unit = new Unit();
unit.setId(1);
unit.setUnitName("TestUnit");
given(unitService.addUnit("TestUnit")).willReturn(unit);
mockMvc.perform(post("/unit").param("unit_name", "TestUnit"))
.andExpect(status().isCreated())
.andExpect(jsonPath("$.unitName").value("TestUnit"))
.andExpect(jsonPath("$.id").value(1));
}
You're mocking the wrong bean. The bean throwing the exception is the service bean, so mock that.
#Test
void testUnitNotFound() throws Exception {
int id = -1;
given(this.service.getUnit(id)).willThrow(new EntityNotFoundException("Unit is not found"));
mockMvc.perform(get("/unit/-1"))
.andExpect(status().isNotFound())
.andExpect(content().contentType(MediaType.APPLICATION_JSON));
}
The problem with the testUnitNotFound() test not working is that you are expecting something from the mocked repository to happen inside a service which is also mocked.
If the service is mocked, then no implementation is invoked. Only a default value is returned which is null. And therefore no exception is thrown as expected...
If you want to have the flexibility of having most of the service mocked but having rest of them having their original implementations called, then you should change the:
#MockBean
UnitService unitService;
into
#SpyBean
UnitService unitService;

Mock method return type in java

Below is main code consist of one util class and service class using it
#PropertySource("classpath:atlas-application.properties")
public class ApacheAtlasUtils {
#Value("${atlas.rest.address}")
private String atlasURL;
#Value("${atlas.rest.user}")
private String atlasUsername;
#Value("${atlas.rest.password}")
private String atlasPassword;
private AtlasClientV2 client;
public AtlasClientV2 createClient() {
if (client == null) {
return new AtlasClientV2(new String[] {atlasURL}, new String[] {atlasUsername, atlasPassword});
} else {
return client;
}
}
}
Service Class is below :-
#Override
public Page<SearchResultDto> findFilesWithPages(QueryParent queryParent, Pageable pageable)
throws AtlasServiceException {
// Some code
client = new ApacheAtlasUtils().createClient();
//some code
}
I am writing unit test for service method and I am getting exception for createClient method asking for values for url, username and password which should not happen as this should be mocked but the mocking is giving me below error
java.lang.IllegalArgumentException: Base URL cannot be null or empty.
at com.google.common.base.Preconditions.checkArgument(Preconditions.java:141)
at org.apache.atlas.AtlasServerEnsemble.<init>(AtlasServerEnsemble.java:35)
at org.apache.atlas.AtlasBaseClient.determineActiveServiceURL(AtlasBaseClient.java:318)
at org.apache.atlas.AtlasBaseClient.initializeState(AtlasBaseClient.java:460)
at org.apache.atlas.AtlasBaseClient.initializeState(AtlasBaseClient.java:448)
at org.apache.atlas.AtlasBaseClient.<init>(AtlasBaseClient.java:132)
at org.apache.atlas.AtlasClientV2.<init>(AtlasClientV2.java:82)
at com.jlr.stratus.commons.utils.ApacheAtlasUtils.createClient(ApacheAtlasUtils.java:40)
at com.jlr.stratus.rest.service.impl.FileSearchService.findFilesWithPages(FileSearchService.java:49)
The Test code is as follows:-
private FileSearchService fileSearchService;
#Spy
private ApacheAtlasUtils apacheAtlasUtils;
#Mock
private AtlasClientV2 client;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
fileSearchService = new FileSearchService();
}
#Test
public void findFilesWithPages_searchAll() throws AtlasServiceException {
Mockito.doReturn(client).when(apacheAtlasUtils).createClient();
service.search(queryParent,pageable);
}
Your idea with spying is adequate (you can even go for mocking if you do not actually need any true implementation of that class).
The problem lies in the implementation:
// Some code
client = new ApacheAtlasUtils().createClient();
//some code
}
Instead of having the ApacheAtlasUtils as an instance variable (or a supplier method) you create the instance on the fly.
Mockito is not smart enough to catch that operation and replace the real object with you spy.
With the supplier method you can set up your test as follows:
#Spy
private FileSearchService fileSearchService = new FileSearchService();
#Spy
private ApacheAtlasUtils apacheAtlasUtils = new ApacheAtlasUtils();
#Mock
private AtlasClientV2 client;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
doReturn(apacheAtlasUtils).when(fileSearchService).getApacheUtils();
}
in your SUT:
#Override
public Page<SearchResultDto> findFilesWithPages(QueryParent queryParent, Pageable pageable)
throws AtlasServiceException {
// Some code
client = getApacheUtils().createClient();
//some code
}
ApacheAtlasUtils getApacheUtils(){
return new ApacheAtlasUtils();
}

Test a controller with Junit?

I had some trouble setting up unit test with my spring boot application. My main issue is with the "model" object that's needed in my controller, but I can't find a way to recreate it in my test, which is required to use my function.
here are the function I want to test
#Controller
public class AjoutAbscenceControler {
#Autowired
private AbsenceRepository absenceRepository;
#RequestMapping(value = { "/addAbsence" }, method = RequestMethod.GET)
public String showAddAbsencePage(Model model) {
Absence absence = new Absence();
model.addAttribute("Absence", absence);
return "addAbsence";
}
#RequestMapping(value = { "/addingAbsence" }, method = RequestMethod.POST)
public String saveAbsence(Model model, #ModelAttribute("absence") Absence absence) {
if (absence.getName() != null && absence.getName().length() > 0) {
absenceRepository.save(absence);
}
return "redirect:/userList";
}
}
I did try something like that
#RunWith(MockitoJUnitRunner.class)
public class AjoutAbscenceControlerTest {
#Mock
VacationRepository vacationRepository;
#Mock
CategoryRepository categoryRepository;
#InjectMocks
AjoutAbscenceControler controler;
public MockMvc mockMvc;
#Before
public void setUp() throws Exception{
mockMvc = MockMvcBuilders.standaloneSetup(controler).build();
}
#Test
public void showAddAbsencePagetest() {
AjoutAbscenceControler ajoutAbscenceControler =new AjoutAbscenceControler();
assertEquals("addAbsence",ajoutAbscenceControler.showAddAbsencePage(controler));
}
}
but I don't find any way to create a springfarmwork.ui.Model
If you're testing the logic of your controller you probably shouldn't create a Model object, but mock it, and verify the interactions against it:
#Mock
private Model model;
#Test
public void showAddAbsencePagetest() {
// Should probably be initialized in a #Before method,
// Initialized here for clarity only
AjoutAbscenceControler ajoutAbscenceControler = new AjoutAbscenceControler();
assertEquals("addAbsence", ajoutAbscenceControler.showAddAbsencePage(model));
Mockito.verify(model).addAttribute(eq("Absence"), any(Absence.class));
}

Categories