Spring Boot Controller Test Failing - spring-boot

I have a RestController that has just one method for http GET and is taking no input arguments. It is calling the service method which takes some arguments. Below is the controller snippet.
#RequestMapping(value = "/leagueResults", method = RequestMethod.GET)
public List<LeagueTableEntry> getResults(){
List<LeagueTableEntry> leagueTableEntryList = new ArrayList<>();
List<Match> listOfMatches = getListOfMatches();
leagueTableEntryList = leagueService.getResults(listOfMatches);
return leagueTableEntryList;
}
Below is my ControllerTest class snippet
#RunWith(SpringRunner.class)
#WebMvcTest(LeagueController.class)
#WebAppConfiguration
public class LeagueControllerTest {
#Autowired
private MockMvc mvc;
#MockBean
private LeagueService leagueService ;
private List<LeagueTableEntry> leagueEntryList;
private List<Match> matchList;
#Before
public void setUp() throws Exception
{
MockitoAnnotations.initMocks(this);
createSampleInputData();//This method populates the instance variable matchList
getLeagueEntryOutput();//This method populates the instance variable leagueEntryList
}
#Test
public void checkNoOfRecordsReturned()throws Exception {
try{
Mockito.when(leagueService.getResults(matchList)).thenReturn(leagueEntryList);
mvc.perform(get("/leagueResults").contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$", hasSize(4)));
}
catch(Exception e){
throw new Exception();
}
}
private void getLeagueEntryOutput(){
leagueEntryList = new ArrayList<>();
leagueEntryList.add(new LeagueTableEntry());
leagueEntryList.add(new LeagueTableEntry());
leagueEntryList.add(new LeagueTableEntry());
leagueEntryList.add(new LeagueTableEntry());
}
So, here I am expecting the count of objects in the returned list as 4, but it is coming as 0.So, my test is failing. Can you please let me know what am i missing.

I think you can instead of writing
Mockito.when(leagueService.getResults(matchList)).thenReturn(leagueEntryList);
write
Mockito.when(leagueService.getResults(Mockito.anyList())).thenReturn(leagueEntryList);
Also if this didn't work I would need to get the implementation of
List<Match> listOfMatches = getListOfMatches();

Related

How to write Junit test cases for this class

#DeleteMapping(value = "/{id}", produces = APPLICATION_JSON_VALUE)
public ResponseEntity<Void> delete(#PathVariable Long id) {
log.debug("Delete by id Logo : {}", id);
try {
Logo entr = new Logo();
entr.setId(id);
logoRepository.delete(entr);
return ResponseEntity.ok().build();
} catch (Exception x) {
return ResponseEntity.status(HttpStatus.CONFLICT).build();
}
}
For testing controllers we could mock mvc. Inject mock of service layers inside the controller.
Since you have mock for your service you could mock the response that service should return for a transaction using Mockito.when statement.
A sample code will be like.
#RunWith(SpringRunner.class)
#WebMvcTest(controllers = HelloController.class)
public class HelloWorldTest {
#Autowired
private MockMvc mockMvc;
#MockBean
private HelloService service;
#Test
public void testShouldReturnMessage() throws Exception {
when(service.sayHello()).thenReturn("Hello World");
mockMvc.perform(MockMvcRequestBuilders.get("/hello").accept(MediaType.ALL))
.andExpect(MockMvcResultMatchers.status().is(200))
.andExpect(MockMvcResultMatchers.content().string("Hello World"))
.andExpect(MockMvcResultMatchers.header().string("Content-Type", "text/plain;charset=UTF-8"))
.andExpect(MockMvcResultMatchers.header().string("Content-Length", "11"));
}
}
Reference - https://www.nexsoftsys.com/articles/spring-boot-controller-unit-testing.html#:~:text=Unit%20testing%20Spring%20Boot%20controllers%20Technology%20Unit%20testing,is%20to%20validate%20each%20unit%20performs%20as%20designed.

#MOCK in Junit 5 returns NULL when using #Value in constructor

I am writing test cases for a project which uses File inpurstream at multiple places. Due to the issues with PowerMock and Junit5, I ended up using a Constructor with #Value to pass file paths to the class. Sample code will show.
Now When I use the constructor with #Value. The test cases for File inputStream work perfectly. But #MOck for any other class returns NULL.
I comment the constructor and #Mock starts working.
any One faced this before?
Class to be tested:
#Component
public class test {
TestUtils testUtil;
String nodeConfigFilePath;
String genConfigFilePath;
public test (#Value("${node.config.path}") String nodeConfigFilePath,
#Value("${genConfig.path}", #Autowired TestUtils testUtil) String genConfigFilePath) {
this.nodeConfigFilePath=nodeConfigFilePath;
this.genConfigFilePath= genConfigFilePath;
this.testUtil = testUtil;
}
public boolean filterConfig(JSONObject Json) {
if(testUtil.iterateJsonForPatternMatch(Json))
return true;
else
return false;
}
public void loadConfigFromJson() {
ObjectMapper mapper = new ObjectMapper();
TypeReference<Map<String, String>> typeRef = new TypeReference<Map<String, String>>() {
};
try {
InputStream inputStream = new FileInputStream(nodeConfigFilePath);
Map<String, String> nodeConfig = new HashMap<String, String>();
nodeConfig = mapper.readValue(inputStream,typeRef);
<do something>
}
}
catch(Exception e) {
}
}
}
Test Class:
#ExtendWith(MockitoExtension.class)
public class test {
#InjectMocks
test test;
#Mock
TestUtils testUtil;
#Test
public void testFilterConfig_success() throws Exception{
JSONObject jsonObj = new JSONObject();
when(testUtil.iterateJsonForPatternMatch(jsonObj)).thenReturn(true);
assertEquals(true, test.filterConfig(jsonObj));
}
#Test
public void testloadConfigFromJson_success() throws Exception{
test = new NotificationFilter(nodeConfigFile.getAbsolutePath(),genConfigJsonFile.getAbsolutePath(), testUtil);
test.loadConfigFromJson();
}
}
FYI: I changed the method names and created a dummy class for demo purpose.
So If Now I remove the #Value constructor, It starts working and no Null pointer for testUtil. But testloadConfigFromJson_success() starts to fail. And Vice versa. Can anyone explain why this is the case?
UPDATE: moved autoiring to constructor and passed the TestUtil instance via constructor in Test class. It seems to do the trick. I am not sure if its correct

Null Pointer Exception while calling a RestController using Mockmvc perform() method in SpringBoot

I am using MockMvc for the first type. What I am doing is testing a Restcontroller in SPringboot.
I have a Restcontroller like this,
#RequestMapping("/address")
public class AddressController {
#RequestMapping("/createAddress")
public Address craeteAddress(Address address)
{
Address add=addressService.createAdd(address);
return add;
}
#RequestMapping("/getAll")
public List<Address> getAll()
{
return addressService.getAll();
}
}
Now my test class looks like this,
public class AddressControllerTest {
AddressService addressService = mock(AddressService.class);
#Autowired
MockMvc mockMvc;
private static final String ADDRESS_DTO_JSON =
"{" +
"\"id\":\"123\"," +
"\"pacsId\":\"345\"," +
"}";
List<Object> object = new ArrayList<Object>();
#Before
public void setup() {
}
#Test
public void createAddressTest() throws Exception {
//System.out.println("The Json Content :" + ADDRESS_DTO_JSON);
this.mockMvc
.perform(get("address/getAll"))
.andExpect(status().isOk())
.andReturn();
}
}
I am trying to call the 'address/getAll' method in the restcontroller. When i run the junit method it says 'Null Pointer Exception' near the .perform(get("address/getAll")) line.
I did some research but did not work out. Can someone please help ?
I think you misconfigured your test class.
Try something like this:
#RunWith(SpringRunner.class)
#WebMvcTest(AddressController.class)
public class AddressControllerTest {
#Autowired
MockMvc mockMvc;
}

Spring MVC release 4.2.6 seems does not inject mock service into the controller when testing controller method

I really searched and followed the steps of creating a unit test class for spring MVC controller, however unit test is running with a green pass flag but the framework uses the original service class and it calls to the database. I mocked the class and used #InjectMocks together with MockitoAnnotations.initMocks(this). Still when the test runs, the controller uses original service object rather than the mocked object. I really appreciate if somebody can help me in this regards.
Here is UserManager(service class), UserRegisterController(controller), TestUserRegisterController (Test class) classes with a picture of the Eclipse package structure
Service :
#Service
public class UserManager {
protected Map<String, String> getAllCertificates() {
Map<String, String> allCertificates = new HashMap<String, String>();
//call to database
return allCertificates;
}
protected User getUser(int userId) {
//create session
User user = session.get(User.class, userId);
//close session
return user;
}
}
Controller :
#Controller
public class UserRegisterController {
#Autowired
private UserManager manager;
#InitBinder
public void initBinder(WebDataBinder binder) {
//do some work
}
#RequestMapping(value = "/user.html", method = RequestMethod.GET)
public ModelAndView getUser(#RequestParam(value="userId", defaultValue="-1") String userId) {
User user1;
user1 = this.manager.getUser(Integer.parseInt(userId));
if (user1 == null) {
user1 = new User();
}
ModelAndView view = new ModelAndView("User", "user1", user1);
view.addObject("allCertificatesMap", this.manager.getAllCertificates());
return view;
}
#ModelAttribute
public void setModelAttribute(Model model) {
model.addAttribute("PageHeader", "lable.pageHeader");
}
}
Test class :
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("test-spring-dispatcher-servlet.xml")
#WebAppConfiguration
public class TestUserRegisterController {
#Mock
private UserManager userManager;
#InjectMocks
private UserRegisterController userRegisterController;
#Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
#Before
public void setUp() throws Exception {
// Process mock annotations
MockitoAnnotations.initMocks(this);
User user2 = new User();
user2.setUserId(10006);
user2.setUserName("Reza");
user2.setHobby("Quadcopter");
user2.setPhone("4032376295");
when(this.userManager.getUser(10006)).thenReturn(user2);
when(this.userManager.getAllCertificates()).thenReturn(new HashMap<String, String>());
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
#Test
public void getUser() {
try {
this.mockMvc.perform(get("/user.html").param("userId", "10006"))
.andExpect(status().isOk())
.andExpect(forwardedUrl("/WEB-INF/jsp/User.jsp"))
.andExpect(MockMvcResultMatchers.view().name("User"))
.andExpect(model().attributeExists("allCertificatesMap"));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Package hierarchy
Use #RunWith(MockitoJUnitRunner.class) to get the #InjectMocks and other annotations to work

Setting session attributes for JUnits on Spring 3.2

I'm having trouble setting session attributes for a test. I am using MockMvc to test calls to a controller. The session model has a member attribute on it (representing the person who has logged in). The SessionModel object is added as a session attribute. I was expecting it to be populated in the ModelMap parameter to formBacking method below, but the ModelMap is always empty.
The controller code works fine when running through the webapp, but not in the JUnit. Any idea what I could be doing wrong?
Here is my JUnit Test
#Test
public void testUnitCreatePostSuccess() throws Exception {
UnitCreateModel expected = new UnitCreateModel();
expected.reset();
expected.getUnit().setName("Bob");
SessionModel sm = new SessionModel();
sm.setMember(getDefaultMember());
this.mockMvc.perform(
post("/units/create")
.param("unit.name", "Bob")
.sessionAttr(SessionModel.KEY, sm))
.andExpect(status().isOk())
.andExpect(model().attribute("unitCreateModel", expected))
.andExpect(view().name("tiles.content.unit.create"));
}
and here is the controller in question
#Controller
#SessionAttributes({ SessionModel.KEY, UnitCreateModel.KEY })
#RequestMapping("/units")
public class UnitCreateController extends ABaseController {
private static final String CREATE = "tiles.content.unit.create";
#Autowired
private IUnitMemberService unitMemberService;
#Autowired
private IUnitService unitService;
#ModelAttribute
public void formBacking(ModelMap model) {
SessionModel instanceSessionModel = new SessionModel();
instanceSessionModel.retrieveOrCreate(model);
UnitCreateModel instanceModel = new UnitCreateModel();
instanceModel.retrieveOrCreate(model);
}
#RequestMapping(value = "/create", method = RequestMethod.GET)
public String onCreate(
#ModelAttribute(UnitCreateModel.KEY) UnitCreateModel model,
#ModelAttribute(SessionModel.KEY) SessionModel sessionModel) {
model.reset();
return CREATE;
}
#RequestMapping(value = "/create", method = RequestMethod.POST)
public String onCreatePost(
#ModelAttribute(SessionModel.KEY) SessionModel sessionModel,
#Valid #ModelAttribute(UnitCreateModel.KEY) UnitCreateModel model,
BindingResult result) throws ServiceRecoverableException {
if (result.hasErrors()){
return CREATE;
}
long memberId = sessionModel.getMember().getId();
long unitId = unitService.create(model.getUnit());
unitMemberService.addMemberToUnit(memberId, unitId, true);
return CREATE;
}
}
For your test class add the #WebAppConfiguration annotation and autowire the following as well.(WebApplicationContext and MockHttpSession )
#RunWith(SpringJUnit4ClassRunner.class)
#WebAppConfiguration
#ContextConfiguration({ "classpath:springDispatcher-servlet.xml" })
public class MySessionControllerTest {
#Autowired WebApplicationContext wac;
#Autowired MockHttpSession session;
private MockMvc mockMvc;
#Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
#Test
public void testUnitCreatePostSuccess() throws Exception {
UnitCreateModel expected = new UnitCreateModel();
expected.reset();
expected.getUnit().setName("Bob");
SessionModel sm = new SessionModel();
sm.setMember(getDefaultMember());
session.setAttribute(SessionModel.KEY, sm);
this.mockMvc.perform(
post("/units/create")
.session(session)
.param("unit.name", "Bob")
.andExpect(status().isOk())
.andExpect(model().attribute("unitCreateModel", expected))
.andExpect(view().name("tiles.content.unit.create"));
}
}

Resources