Below is my code for which I need to write testcase.
Here Entity Manager gives null pointer in testcase.
Error : java.lang.NullPointerException
Think so this is because of PersistenceContext not getting injected properly.
Can someone help on this ?
#Component(value = "bacservice")
public class ServiceImpl {
#PersistenceContext
private EntityManager em;
public List<String> getScopeIdsForLoggedInUser(List<BaasScope> scopes) throws Exception {
Query query = em.createNativeQuery(formattedQuery);
List<String> scopeList = query.getResultList();
}
}
Tried the below testcase
#RunWith(SpringRunner.class)
public class ServiceImplTest {
#Spy
private ServiceImpl serviceImpl;
private EntityManager em;
private Query query;
#Before
public void init() throws Exception {
MockitoAnnotations.openMocks(this);
em = Mockito.mock(EntityManager.class);
query = Mockito.mock(Query.class);
}
#Test
public void getScopeIdsForLoggedInUserTest() throws Exception {
List<String> scopeList = new ArrayList<String>();
List<String> scopes = new ArrayList<String>();
when(em.createNativeQuery("query")).thenReturn(query);
when(query.getResultList()).thenReturn(scopeList);
List<String> value = serviceImpl.getScopeIdsForLoggedInUser(scopes);
assertEquals(scopeList, value);
}
}
Related
I am trying to test with Junit for my StudentRowmapper class, I am a bit new for Unit Test and also Mock test, I have asked smilar question before, but I could not figure out how to mock Datetime.of object. When I run my test; DateTimes throws null pointer exception
StudentGroupList below;
#Getter
#Setter
public class StudentGroupList {
private String studentId;
private LocalDateTime studentDate();
}
StudentGroupListRowMapper below;
public class StudentGroupListRowMapper implements RowMapper<StudentGroupList> {
#Override
public StudentGroupList mapRow(Resultset rs, int rowNum) throws SQLException {
StudentGroupList studentGroupList = new StudentGroupList();
studentGroupList.setStudentId(rs.getString("student_id"));
studentGroupList.setStudentDate(rs.getTimestamp("student_date").toLocalDateTime());
return studentGroupList;
}
}
My Unit Test below;
private static int rowNum = 2;
private StudentGroupListRowMapper mapper;
private ResultSet resultSet;
private StudentGroupList studentGroupList;
#Before
public void setUp() {
studentGroupList = new StudentGroupList();
mapper = new StudentGroupListRowMapper();
resultSet = mock(ResultSet.class);
}
#Test
public void testmapRow() throws SQLException {
when(resultSet.getString("student_id")).thenReturn("sutdent-id-1");
when(resultSet.getTimeStamp("student_date").toLocalDateTime()).thenReturn(LocalDateTime.of(2001,3,17,2,10)));
studentGroupList mapper.mapRow(resultSet, rowNum);
assertEquals(studentGroupList .getStudentId(), "sutdent-id-1");
assertEquals(studentGroupList .getStudentDate, LocalDateTime.of(2001,3,17,2,10));
}
private static int rowNum = 2;
#InjectMocks
private StudentGroupListRowMapper mapper;
#Mock
private ResultSet resultSet;
#Mock
private StudentGroupList studentGroupList;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
studentGroupList = new StudentGroupList();
mapper = new StudentGroupListRowMapper();
resultSet = createResultSet();
}
createResultSet(){
resultSet = new ResultSet();
resultSet.setStudentId(111);
resultSet.setStudentId(LocalDateTime.of(2001,3,17,2,10));
}
#Test
public void testmapRow() throws SQLException {
studentGroupList = mapper.mapRow(resultSet, rowNum);
asserThat(studentGroupList.getStudentId()).isEqualTo(110);
asserThat(studentGroupList.getStudentId()).isEqualTo(LocalDateTime.of(2001,3,17,2,10));
}
I suggest you convert String student id to an int or parse the string. I just used an integer. From what I could gather, this is my solution for you. Hope you could understand the structure of the test. There are more ways to do this
I have a spring boot REST API with a GET method that returns data available in a DB. I am attempting to write an integration test to test this API method. I have configured the test to use the H2 database. I am trying to add some mock data to the database before the test is executed and see if the API retrieves that data. Following is the code I have written so far.
#RunWith(SpringRunner.class)
#SpringBootTest
#AutoConfigureMockMvc
#TestPropertySource(locations = "classpath:application-test.properties")
public class MetaControllerTest {
#Autowired
private MockMvc mvc;
#Autowired
private ProvinceDAO provinceDAO;
#Transactional
#Before
public void addData () {
Province southern = getProvinceEntity("Southern", "දකුණ", "தென்");
provinceDAO.createEntity(southern);
System.out.println(provinceDAO.findAll(Province.class).size());
}
#Test
public void testGetProvinces() throws Exception {
MvcResult result = mvc.perform(get("/meta/provinces"))
.andExpect(status().isOk())
.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
.andReturn();
System.out.println(result.getResponse().getContentAsString());
}
}
However, when I run this code, I am getting an error saying "org.springframework.dao.InvalidDataAccessApiUsageException: No transactional EntityManager available; nested exception is java.lang.IllegalStateException: No transactional EntityManager available"
I have also attempted using #MockBean instead of #Autowired to bind the provinceDAO. Even though this prevents the error, it does not persist the entity in the database.
How should I write my testcase to test my method here?
Update:
application-test.properties
spring.datasource.url = jdbc:h2:mem:test
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.H2Dialect
Entity -> Province.java
#Entity
#Table(name = "w4a_province")
public class Province {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private int id;
#Column(name = "province_name")
private String name;
#Column(name = "province_name_si")
private String nameSi;
#Column(name = "province_name_ta")
private String nameTa;
.
.
}
GenericDAO.java
#Repository
public class GenericDAO<T> implements IGenericDAO<T> {
#PersistenceContext
private EntityManager em;
#Override
public Session getCurrentSession() {
return this.em.unwrap(Session.class);
}
#Override
public T findByPrimaryKey(Class<T> clazz, Object primaryKey) {
return getCurrentSession().find(clazz, primaryKey);
}
#Override
public List<T> findAll(Class<T> clazz) {
DetachedCriteria criteria = DetachedCriteria.forClass(clazz);
return criteria.getExecutableCriteria(getCurrentSession()).list();
}
#Override
public T createEntity(T entity) {
getCurrentSession().save(entity);
return entity;
}
ProvinceDAOImpl.java
#Repository
public class ProvinceDAOImpl extends GenericDAO<Province> implements ProvinceDAO {
}
MetaController.java
#RestController
#PreAuthorize("permitAll()")
public class MetaController {
private final MetaService metaService;
#Autowired
public MetaController(MetaService metService) {
this.metaService = metService;
}
#GetMapping("/meta/provinces")
public ResponseEntity<List<ProvinceDTO>> getProvinces() {
if (logger.isDebugEnabled()) {
logger.debug("Retrieving list of provinces.");
}
List<ProvinceDTO> provinces = metaService.getProvinces();
return ResponseEntity.ok(provinces);
}
}
MetaServiceImpl.java
#Service
#Transactional
public class MetaServiceImpl implements MetaService {
private final ProvinceDAO provinceDAO;
#Autowired
public MetaServiceImpl(ProvinceDAO provnceDAO) {
this.provinceDAO = provnceDAO;
}
public List<ProvinceDTO> getProvinces() {
if (logger.isDebugEnabled()) {
logger.debug("Obtaining a list of provinces from database.");
}
List<Province> entities = provinceDAO.findAll(Province.class);
if (logger.isDebugEnabled()) {
logger.debug("Converting province entities to dtos.");
}
List<ProvinceDTO> dtos = new ArrayList<>();
for (int i = 0; i < entities.size(); i++) {
Province entity = entities.get(i);
if (LocaleContextHolder.getLocale().getLanguage().equals(
GlobalConstants.LanguageIdentifiers.SINHALA_LANGUAGE_TAG)) {
dtos.add(new ProvinceDTO(entity.getId(), entity.getNameSi()));
} else if (LocaleContextHolder.getLocale().getLanguage().equals(
GlobalConstants.LanguageIdentifiers.TAMIL_LANGUAGE_TAG)) {
dtos.add(new ProvinceDTO(entity.getId(), entity.getNameTa()));
} else {
dtos.add(new ProvinceDTO(entity.getId(), entity.getName()));
}
}
return dtos;
}
}
I managed to feed the database with the required data by placing a SQL script data-h2.sql with insert queries at the test/resources folder. This prevented the requirement to use an EntityManager or a DAO.
Furthermore, I added the following property to the application-test.properties file.
spring.datasource.platform=h2
In Order to test Rest Api You can try functional test as well as integration test.
You can prepare your own response formate as required and check whether the same is returned or else you can also verify whether the data from db is fine or not.Plz check the below example
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest(classes = FactsMain.class)
#WebAppConfiguration
public abstract class BaseTest {
protected MockMvc mvc;
#Autowired
WebApplicationContext webApplicationContext;
protected void setUp() {
mvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
protected String mapToJson(Object obj) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.writeValueAsString(obj);
}
protected <T> T mapFromJson(String json, Class<T> clazz)
throws JsonParseException, JsonMappingException, IOException {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readValue(json, clazz);
}
}
In First test case i am forming the response format and trying to return the same and then validating the same.Here i don't need the db data so i have kept service as mock instead of auto wired.And used ObjectMapper for converting json to java and then java obj to json from base Test class.
public class PersonalDetailsControllerTest extends BaseTest {
#MockBean
private IPersonalService service;
private static final String URI = "/api/personalDetails";
#Override
#Before
public void setUp() {
super.setUp();
}
#Test
public void testGet() throws Exception {
PersonalDetailsEntity entity = new PersonalDetailsEntity();
List<PersonalDetailsEntity> dataList = new ArrayList<PersonalDetailsEntity>();
FactsAdminResponse<PersonalDetailsEntity> dataResponse = new FactsAdminResponse<PersonalDetailsEntity>();
entity.setId(1);
entity.setName(“Anthony Holmes”);
entity.setAge(26);
entity.setCity(“Banglore”);
entity.setCountry(“India”);
dataList.add(entity);
dataResponse.setData(dataList);
Mockito.when(service.getBuildings()).thenReturn(dataList);
RequestBuilder requestBuilder = MockMvcRequestBuilders.get(URI)
.accept(MediaType.APPLICATION_JSON);
MvcResult mvcResult = mvc.perform(requestBuilder).andReturn();
MockHttpServletResponse response = mvcResult.getResponse();
String expectedJson = this.mapToJson(dataResponse);
String outputInJson = mvcResult.getResponse().getContentAsString();
assertEquals(HttpStatus.OK.value(), response.getStatus());
assertEquals(expectedJson, outputInJson);
}
}
In below case we are getting the actual data in json format as we are doing rest api call and then just validating the status apart from status you can also cross check the data
public class PersonalDetailsControllerTest extends BaseTest {
private static final String URI = "/api/personalDetails";
#Override
#Before
public void setUp() {
super.setUp();
}
#Test
public void getGet() throws Exception {
MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.get(URL)
.accept(MediaType.APPLICATION_JSON_VALUE)).andReturn();
int status = mvcResult.getResponse().getStatus();
assertEquals(200, status);
String content = mvcResult.getResponse().getContentAsString();
//you got the content in string format now you can also validate the data
}
this is an update to my previous question. I have a Utility class which I already manage to cover with my unit test except when the condition returns false.
Here is my class:
#Component
public class Utils {
#Autowired
private ObjectMapper mapper = new ObjectMapper();
#Autowired
private LoggingService loggingService;
public <E> String mapToJsonString(E object) {
try {
if (object == null) {
throw new IOException(ErrorMessage.ERROR_PROCESSING_JSON_NULL);
}else {
return mapper.enable(SerializationFeature.INDENT_OUTPUT).writeValueAsString(object); //NullPointer Here
}
} catch (IOException e) {
loggingService.logError(this.getClass().getName(), "1", ErrorMessage.ERROR_MAPPING_TO_JSONSTRING, e);
return "";
}
}
}
and here is my unit test
#RunWith(SpringRunner.class)
#ContextConfiguration(classes = ATMMonitoringApplication.class, initializers = ConfigFileApplicationContextInitializer.class)
public class ObjectToJsonStringTest {
#SpyBean
private ATM atm;
#Autowired
private Utils utils;
#MockBean
private ObjectMapper mapper;
#MockBean
private LoggingService loggingService;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
myModelClass = new MyModelclass();
myModelClass.setStatus("U");
myModelClass.setTermCode("001");
myModelClass.setLocation("BGC");
}
#Test
public void testObjectToJson() throws JsonProcessingException {
String output = utils.mapToJsonStringmyModelClass
assertNotNull(output);
}
#Test
public void testObjectToJsonNull() throws JsonProcessingException {
String output = utils.mapToJsonString(null);
assertNull(output);
}
#Test
public void testJsonParsingException() {
myModelClass = new MyModelclass();
myModelClass = null;
String output = utils.mapToJsonString(myModelClass);
Mockito.when(loggingService.logError(this.getClass().getName(), "1", ErrorMessage.ERROR_MAPPING_TO_JSONSTRING, new Exception()))
.thenReturn("");
assertThat(output).isEmpty();
}
}
Stack trace says that i have a null pointer on this line of code:
return mapper.enable(SerializationFeature.INDENT_OUTPUT).writeValueAsString(object);
Please help me on this. Thanks
Solved it. I just change this
#Mock
private ObjectMapper mapper;
From #MockBean and it covered the whole class.
I am trying to test the following controller:
#RepositoryRestController
#RequestMapping("movies")
public class MovieController {
private MovieService movieService;
private PagedResourcesAssembler<Movie> pagedAssembler;
private MovieResourceAssembler movieResourceAssembler;
#Autowired
public void setMovieService(MovieService movieService) {
this.movieService = movieService;
}
#Autowired
public void setPagedAssembler(PagedResourcesAssembler<Movie> pagedAssembler) {
this.pagedAssembler = pagedAssembler;
}
#Autowired
public void setMovieResourceAssembler(MovieResourceAssembler movieResourceAssembler) {
this.movieResourceAssembler = movieResourceAssembler;
}
// Return all movies with pagination
#GetMapping
public ResponseEntity<?> getAllMovies(Pageable pageable) {
Page<Movie> moviePage = this.movieService.getAllMovies(pageable);
// Remove some unnecessary fields
//this.movieService.removeUndesirableFieldsFromListing(moviePage);
return ResponseEntity.ok(this.pagedAssembler.toResource(moviePage, this.movieResourceAssembler));
}
}
and here's the test:
#RunWith(SpringRunner.class)
#SpringBootTest
#AutoConfigureMockMvc
public class MovieControllerTest {
#Autowired
private MockMvc mockMvc;
#MockBean
private MovieService movieService;
#Test
public void getAllMovies_PageableGiven_ShouldReturnMoviesPage() throws Exception {
List<Movie> movieList = new ArrayList<>();
movieList.add(new Movie());
movieList.add(new Movie());
Page<Movie> moviePage = new PageImpl<>(movieList);
given(this.movieService.getAllMovies(PageRequest.of(0,2)))
.willReturn(moviePage);
this.mockMvc.perform(get("http://localhost:8080/api/movies?page=1"))
.andExpect(status().isOk());
}
}
i got the following error:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalArgumentException: Page must not be null!
You could use Spring's mockMvc object injecting it inside your test class:
#Autowired
private MockMvc mockMvc;
I have just created a test method using mockMvc.perform method sending a page request:
My controller code:
#GetMapping(produces=MediaType.APPLICATION_JSON_UTF8_VALUE)
public List<BaseResponse> listAllBase(
#PageableDefault(size = 50, page = 2) Pageable pageable) {
// logger.debug("paginación recibida :{}",pageable);
List<BaseResponse> findAllBases = baseService.findAllBases();
return findAllBases;
}
My test code:
mockMvc.perform(get("/base/?size=2&page=0")).andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)) .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
.andExpect(jsonPath("$", hasSize(2))) .andExpect(jsonPath("$", hasSize(2)))
.andExpect(jsonPath("$[0].name", equalToIgnoringCase("margarita")))
See full Class code in my GitHub repo:
Controller:
https://github.com/cristianprofile/spring-boot-mvc-complete-example/blob/develop/spring-boot-mvc-rest/src/main/java/com/mylab/cromero/controller/HelloWorldController.java#L53
Test class method:
https://github.com/cristianprofile/spring-boot-mvc-complete-example/blob/develop/spring-boot-mvc-rest/src/test/java/com/mylab/cromero/controller/RestTestIT.java#L66
Feel free to use it in your project :)
By reading these two Stackoverflow threads ([1] and [2]) and also Spring documentation, it seems that you should use Page with repositories. Example:
PagingAndSortingRepository<User, Long> repository = // … get access to a bean
Page<User> users = repository.findAll(new PageRequest(1, 20));
For your case, it's recommended to use PagedListHolder, instead. Example:
List<Movie> movieList = new ArrayList<>();
movieList.add(new Movie());
movieList.add(new Movie());
PagedListHolder<Movie> holder = new PagedListHolder<>(movieList);
I am trying to mock a method of the Spring framework's JdbcTemplate class. The method has the following signature:
public <T> T queryForObject(String sql, Class<T> requiredType) throws DataAccessException {...}
The mocking is being done as mentioned below:
when(jdbcTemplate.queryForObject(anyString(), eq(String.class))).thenReturn("data");
However, this call throws the following exception
java.lang.ClassCastException: org.mockito.internal.creation.jmock.ClassImposterizer$ClassWithSuperclassToWorkAroundCglibBug$$EnhancerByMockitoWithCGLIB$$ce187d66 cannot be cast to java.lang.String
at test.DaoJdbcTest.setUp(DaoJdbcTest.java:81)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
...
Any idea as to what I am doing wrong?
Thanks in advance~
EDIT:
Here's the full code:
public class DaoJdbc extends NamedParameterJdbcSupport {
public String query(String sql) {
return getJdbcTemplate().queryForObject(sql, String.class);
}
}
public class DaoJdbcTest {
#Mock(answer = Answers.RETURNS_SMART_NULLS)
private JdbcTemplate jdbcTemplate;
private DaoJdbc dao;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
dao = new DaoJdbc();
dao.setJdbcTemplate(jdbcTemplate);
Mockito.when(jdbcTemplate.queryForObject(anyString(), Matchers.eq(String.class))).thenReturn("data");
}
#Test
public void testQuery() {
String ret = dao.query("select 'test' from dual");
assertEquals("data", ret);
verify(jdbcTemplate).queryForObject(anyString(), eq(String.class));
}
}
Remove the answer = Answers.RETURNS_SMART_NULLS. Test passes when I remove that. What does that feature do? The default null behavior works fine for me.
As a bonus, you can also use the MockitoJunitRunner to clean up the code a bit...
#RunWith(MockitoJUnitRunner.class)
public class DaoJdbcTest {
#Mock
private JdbcTemplate jdbcTemplate;
#InjectMocks
private DaoJdbc dao;
#Before
public void setUp() throws Exception {
Mockito.when(jdbcTemplate.queryForObject(anyString(), Matchers.eq(String.class))).thenReturn("data");
}
#Test
public void testQuery() {
String ret = dao.query("select 'test' from dual");
assertEquals("data", ret);
verify(jdbcTemplate).queryForObject(anyString(), eq(String.class));
}
}