I am writing unit tests for my project, but facing some difficulties when calling methods, which work with database. Currently I want to check a method that gets the list of publications that are of users interest, but I am getting NullPointerException:
public class TestPubManager {
private PubManager pFunc;
#Before
public void initialize() {
EntityManager manager = PersistenceManager.INSTANCE.getEntityManager();
em.getTransaction().begin();
PubManager pManager = new PubManager(manager);
}
#Test
public void testGetInterestPubs() {
int res = pManager.getInterestPubs(2).size();
assertEquals(20, res);
}
}
NullPointerException is on the line with int res = pManager.getInterestPubs(2).size();. What am I doing wrong way?
I have found a solution. So the issue was in the constructor - it was not initializing in #Before annotation, but when I put it inside the test, everything worked out fine.
public class TestPubManager {
private PubManager pFunc;
EntityManager manager = PersistenceManager.INSTANCE.getEntityManager();
#Before
public void initialize() {
em.getTransaction().begin();
}
#Test
public void testGetInterestPubs() {
PubManager pManager = new PubManager(manager);
int res = pManager.getInterestPubs(2).size();
assertEquals(20, res);
}
}
Related
I am trying to write unit tests for Repository layer classes with Junit and Mockito.
I have mocked the base class that supplies NamedParameterJdbcOperations and tried to inject into the repo class.
In the repo class, we are loading sql queries from files on classpath. This is done in a method that is annotated with #PostConstruct.
When trying to test a method of the repo, it is not able to find or load the query and thus throwing NullPointerException.
Need help / suggestion on how to deal with such scenario.
PS: I am not allowed to change the repo class implementation.
Attaching the code of repo and test class for reference.
RepositoryImpl.java
#Repository
public class RepositoryImpl extends AppJdbcImpl implements
Repository {
private static final StudentMapper STUDENT_ROW_MAPPER = new StudentMapper();
private static final CourseMapper COURSE_ROW_MAPPER = new CourseMapper();
#Value("classpath:sql/sql1.sql")
private Resource sql1;
private String query1;
#Value("classpath:sql/sql2.sql")
private Resource sql2;
private String query2;
public RepositoryImpl() { }
public RepositoryImpl(NamedParameterJdbcOperations jdbc) {
super(jdbc);
}
#PostConstruct
public void setUp() {
query1 = loadSql(sql1);
query2 = loadSql(sql2);
}
public Iterable<Course> findCoursesByStudentId(int studentId) throws
DataAccessException {
try {
return jdbc().queryForObject(query1,
ImmutableMap.of("studentId", studentId),
COURSE_ROW_MAPPER);
} catch (EmptyResultDataAccessException emptyResult) {
return null;
} catch (DataAccessException e) {
// Need to create exception classes and throw specific exceptions
throw e;
}
}
public Iterable<Student> findStudentsByCourseId(int courseId) throws DataAccessException {
try {
return jdbc().query(query2,
ImmutableMap.of("courseId", courseId),
STUDENT_ROW_MAPPER);
} catch (DataAccessException e) {
// Need to create exception classes and throw specific exceptions
throw e;
}
}
private String loadSql(Resource resource) {
try {
return CharStreams.toString(new InputStreamReader(resource.getInputStream()));
} catch (IOException e) {
return null;
}
}
}
RespositoryImplTest.java
#RunWith(MockitoJUnitRunner.class)
public class RepositoryImplTest {
#Mock
private NamedParameterJdbcOperations jdbc;
#Mock
private ResultSet resultSet;
#Mock
private StudentMapper studentMapper;
#Mock
private CourseMapper CourseMapper;
#InjectMocks
private RepositoryImpl repository;
private Student student1;
private Student student2;
private Course course1;
private Course course2;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
course1 = new Course(1, "Karate");
course2 = new Course(2, "Riding");
course8 = new Course(8, "Swimming");
List<Course> courseList = Arrays.asList(course1, course2, course8);
student1 = new Student(1, "Chuck", "Norris", 27, new Arrays.asList(course1, course2));
student2 = new Student(2, "Bruce", "Lee", 54, new Arrays.asList(course1, course8));
List<Student> studentList = Arrays.asList(student1, student2);
when(jdbc.queryForObject(Matchers.anyString(), anyMap(),
isA(StudentMapper.class)))
.thenAnswer(new Answer() {
#Override
public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
Object[] args = invocationOnMock.getArguments();
int queryParam = Integer.parseInt(args[0].toString());
Iterable<Credentials> result = studentList.stream()
.filter(d -> d.getId() == queryParam)
.collect(Collectors.toList());
return result;
}
});
}
#Test
public void findCoursesByStudentId() {
Iterable<Course> result = repository.findCoursesByStudentId(1);
assertNotNull(result);
}
}
In repo class, exception is thrown as query1 is null.
Need help to properly solving the issue.
Thanks, Baru
#RunWith(MockitoJUnitRunner.class)
you start test with mockito starter, not spring starter. It's mean that spring not provided you beans. Mockito starter nothing know about PostConstruct annotation.
You may call PostConstruct method youself in sturUp junit method or in test method.
I have a tricky situation. I am using MVP architecture for android but thats not important. I have a class called DoStandardLoginUsecase that basically just connects to a server with login info and gets a access token. i am trying to test it. But the problem is the context that i am passing in to it so i can initialize dagger.
public class DoStandardLoginUsecase extends BaseUseCase {
#Inject
UserDataRepository mUserDataRepo;
private StandardLoginInfo loginInfo;
public DoStandardLoginUsecase(Context context) {
/* SEE HERE I AM USING A APPLICATION CONTEXT THAT I PASS TO DAGGER
*/
((MyApplication)context).getPresenterComponent().inject(this);
}
#Override
public Observable<Login> buildUseCaseObservable() {
return mUserDataRepo.doStandardLogin(loginInfo);
}
public void setLoginInfo(StandardLoginInfo loginInfo) {
this.loginInfo = loginInfo;
}
}
and here is the test i have so far:
public class DoStandardLoginUsecaseTest {
DoStandardLoginUsecase standardLoginUsecase;
StandardLoginInfo fakeLoginInfo;
TestObserver<Login> subscriber;
MockContext context;
#Before
public void setUp() throws Exception {
//now when i create the object since its a mock context it will fail when it tries to call real things as these are stubs. So how do i test this object. how do i create an instance of this object ? I am willing to use [daggerMock][1] if that helps also.
standardLoginUsecase = New DoStandardLoginUsecase(context);
fakeLoginInfo = new StandardLoginInfo("fred#hotmail.com","Asdfgh4534");
subscriber = TestObserver.create();
}
#Test
public void buildUseCaseObservable(){
standardLoginUsecase.seLoginInfo(fakeLoginInfo);
standardLoginUsecase.buildUseCaseObservable().subscribe(subscriber);
subscriber.assertNoErrors();
subscriber.assertSubscribed();
subscriber.assertComplete();
}
}
I would do the test like this:
public class DoStandardLoginUsecaseTest {
private DoStandardLoginUsecase target;
private MyApplication contextMock;
#Before
public void beforeEach() {
contextMock = Mockito.mock(MyApplication.class);
// Note that you need to mock the getPresenterComponent
// but I don't know what it returns.
target = new DoStandardLoginUsecase(contextMock);
}
#Test
public void buildUseCaseObservable() {
UserDataRepository userDataMock = Mockito.mock(UserDataRepository.class);
StandardLoginInfo loginInfoMock = Mockito.mock(StandardLoginInfo.class);
target.mUserDataRepo = userDataMock;
target.setLoginInfo(loginInfoMock);
Observable<Login> expected = // create your expected test data however you like...
Mockito.when(userDataMock.doStandardLogin(loginInfoMock)).thenReturn(expected);
Observable<Login> actual = target.buildUseCaseObservable();
Assert.areSame(actual, expected);
}
}
I'm currently using Mockito and In memory Database (H2) in order to test some services and dao.
I've tried to test a method (createRoad) of my service that contains some call of dao method :
#Service(value = "RoadsService")
public class RoadsService implements IRoadsService {
#Autowired
private IRoadsDao roadsDao;
...
#Override
public long createRoad(CreateRoadCriteria criteria) {
String roaCodeToCopy = "";
RoadsCriteria roadsCriteria = new RoadsCriteria();
roadsCriteria.setCe(criteria.getCe());
roadsCriteria.setDeliveryDate(new Date());
List<WebRoadsModel> listRoadsCe = roadsDao
.getRoadsByCEAndDeliveryDate(roadsCriteria);
for (WebRoadsModel wrm : listRoadsCe) {
if (wrm.getRoaCode().endsWith("90")) {
roaCodeToCopy = wrm.getRoaCode();
break;
}
}
criteria.setRoadCode(StringUtils.substring(roaCodeToCopy, 0, 4)
+ criteria.getRoadCode());
// 2. Creation of the new road
long idNewRoad = roadsDao.createNewRoad(criteria);
if (!"".equals(roaCodeToCopy) && listRoadsCe.get(0) != null) {
roaCodeToCopy = listRoadsCe.get(0).getRoaCode();
// 3. Copy dates closed of this trn
RoadsCriteria newRoadCreated = new RoadsCriteria();
newRoadCreated.setCe(criteria.getCe());
newRoadCreated.setRoadId(idNewRoad);
// 4. Paste it for the new road
deliveryCalendarDao.copyClosedDates(roadsDao
.getRoadByCriteria(newRoadCreated).get(0).getRoaCode(),
roaCodeToCopy);
}
return idNewRoad;
}
...
}
I need to mock the method called getRoadsByCEAndDeliveryDate, because the sql query behind that is not managed by the H2 driver (query with "RANK"). Then, I want to use H2 with the other method in this service.
I've tried this :
public class RoadsServiceTest {
#InjectMocks
private RoadsService roadsService;
#Mock
private MockRoadDao roadsDao;
#BeforeClass
public static void setUpClass() throws Exception {
}
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
#Test
public void createRoad(){
CreateRoadCriteria criteria = new CreateRoadCriteria();
criteria.setRoadCode("AA");
criteria.setRoadName("ANAME");
criteria.setCe("2");
criteria.setDriver(1);
criteria.setVehicle(1);
criteria.setSupplier(1);
List<WebRoadsModel> expected = new ArrayList<WebRoadsModel>();
Mockito.when(roadsDao.getRoadsByCEAndDeliveryDate((RoadsCriteria) Mockito.any())).thenReturn(expected);
Mockito.when(roadsDao.getNextVal(Mockito.anyString())).thenCallRealMethod();
Mockito.when(roadsDao.createNewRoad(criteria)).thenCallRealMethod();
long result = roadsService.createRoad(criteria);
Assert.assertEquals(5, result);
}
}
It is almost good except the assertEquals.
According to my sql file used with my in memory database, i have a sql sequence like this :
CREATE SEQUENCE "SEQ_SITI_ROADS" MINVALUE 1 MAXVALUE 99999 INCREMENT BY 1 START WITH 5 CACHE 20 ;
When I run my test, the result is 0.
It seems that the MockRoadDao is not initialized.
public class MockRoadDao extends RoadsDao {
public MockRoadDao() throws DatabaseUnitException, SQLException, MalformedURLException {
IDataSet dataSet = new FlatXmlDataSetBuilder().build(new File("./src/test/resources/dataset.xml"));
DataSource dataSource = TestUtils.dataSource();
IDatabaseConnection dbConn = new DatabaseDataSourceConnection(dataSource);
DatabaseOperation.CLEAN_INSERT.execute(dbConn, dataSet);
User user = new User();
user.setLangCountry("ENFR");
BackendContextHolder.setBackendIdentifier(new BackendIdentifierImpl(user));
final NamedParameterJdbcTemplate jdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
setJdbcTemplate(jdbcTemplate);
}
}
public class TestUtils {
private static final Logger LOG = LoggerFactory.getLogger(TestUtils.class);
public static DataSource datasource;
/**
* #return
*/
public static DataSource dataSource() {
if (datasource == null) {
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
EmbeddedDatabase db = builder.setType(EmbeddedDatabaseType.H2).addScript("classpath:/siti-create.sql").build();
datasource = db;
}
return datasource;
}
...
}
Could you please help me :)
Thank you in advance
Edit :
#Baski : When I remove #Mock and use ReflectionUtils instead, the constructor of MockRoadDAO is called. But, when I run the test, the method roadsDao.getRoadsByCEAndDeliveryDate() is not mocked with Mockito, the method is really called and unfortunately the SQL query is not managed by the H2 driver.
public class RoadsServiceTest {
#InjectMocks
private RoadsService roadsService;
private MockRoadDao roadsDao;
#BeforeClass
public static void setUpClass() throws Exception {
}
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
roadsDao = new MockRoadDao();
ReflectionTestUtils.setField(roadsService, "roadsDao", roadsDao);
}
#Test
public void createRoad(){
CreateRoadCriteria criteria = new CreateRoadCriteria();
criteria.setRoadCode("AA");
criteria.setRoadName("ANAME");
criteria.setCe("2");
criteria.setDriver(1);
criteria.setVehicle(1);
criteria.setSupplier(1);
List<WebRoadsModel> expected = new ArrayList<WebRoadsModel>();
Mockito.when(roadsDao.getRoadsByCEAndDeliveryDate((RoadsCriteria) Mockito.any())).thenReturn(expected);
Mockito.when(roadsDao.getNextVal(Mockito.anyString())).thenCallRealMethod();
Mockito.when(roadsDao.createNewRoad(criteria)).thenCallRealMethod();
long result = roadsService.createRoad(criteria);
Assert.assertEquals(5, result);
}
}
We are building an application which uses Spring Boot. We write unit tests using TestNG and Mockito. However I find it pretty annoying to write when(...) configuration, I would like to use real components instead. I started to use #Spy components instead of mocks and this works pretty well until I need to put a Spy into a Spy. I'd like to avoid loading a Spring Context if possible, because creation of the context is very slow it looks like overkill for me to load it for at max 5 classes.
Is there any way, how could I use real code instead of Mocks and not loading whole Spring context? Or is my approach wrong at all and I should mock out all other classes then the tested one?
The other way to do this and may take some modifying of code on your end is to do it by constructor injection instead of field injection. Basically taking away any need of the spring context for testing. so the same from the other answer
Class to test
#Service
public class RecordServiceImpl implements RecordService
{
private final RecordRepository recordRepository;
#Autowired
public RecordServiceImpl(RecordRepository recordRepository)
{
this.recordRepository = recordRepository;
}
public Record find(String id)
{
return recordRepository.findOne(id);
}
public List<Record> findAll()
{
return recordRepository.findAll();
}
#Transactional
public Record save(Record record)
{
record.setRecordStatus("F");
return recordRepository.save(record);
}
}
Test Case
//#RunWith(SpringJUnit4ClassRunner.class)
//#ContextConfiguration(classes = {RecordServiceTestConfig.class})
public class RecordServiceTest
{
// #Autowired
private RecordRepository recordRepository = Mockito.mock(RecordRepository.class);
// #Autowired
private RecordService recordService;
#Before
public void setup()
{
Mockito.reset(recordRepository);
recordService = new RecordServiceImpl(recordRepository);
}
#Test
public void testFind()
{
Mockito.when(recordRepository.findOne(Mockito.anyString())).thenReturn(null);
Record record = recordService.find("1");
Assert.assertNull(record);
Mockito.verify(recordRepository, Mockito.times(1)).findOne(Mockito.eq("1"));
}
#Test
public void testSave()
{
Mockito.when(recordRepository.save(Mockito.any(Record.class)))
.thenAnswer(new Answer<Record>()
{
#Override
public Record answer(InvocationOnMock invocation) throws Throwable
{
Record record = (Record) invocation.getArguments()[0];
Assert.assertEquals("F", record.getRecordStatus());
return record;
}
});
Record record = new Record();
record = recordService.save(record);
Assert.assertNotNull(record);
Mockito.verify(recordRepository, Mockito.times(1)).save(Mockito.eq(record));
}
#Test
public void findAll()
{
Mockito.when(recordRepository.findAll()).thenReturn(new ArrayList<Record>());
List<Record> records = recordService.findAll();
Assert.assertNotNull(records);
Assert.assertEquals(0, records.size());
Mockito.verify(recordRepository, Mockito.times(1)).findAll();
}
}
I think your looking for like this with the use of #ContextConfiguration and #Configuration
Class to test
#Service
public class RecordServiceImpl implements RecordService
{
#Autowired
private RecordRepository recordRepository;
public Record find(String id)
{
return recordRepository.findOne(id);
}
public List<Record> findAll()
{
return recordRepository.findAll();
}
#Transactional
public Record save(Record record)
{
record.setRecordStatus("F");
return recordRepository.save(record);
}
}
Test Class
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {RecordServiceTestConfig.class})
public class RecordServiceTest
{
#Autowired
private RecordRepository recordRepository;
#Autowired
private RecordService recordService;
#Before
public void setup()
{
Mockito.reset(recordRepository);
}
#Test
public void testFind()
{
Mockito.when(recordRepository.findOne(Mockito.anyString())).thenReturn(null);
Record record = recordService.find("1");
Assert.assertNull(record);
Mockito.verify(recordRepository, Mockito.times(1)).findOne(Mockito.eq("1"));
}
#Test
public void testSave()
{
Mockito.when(recordRepository.save(Mockito.any(Record.class)))
.thenAnswer(new Answer<Record>()
{
#Override
public Record answer(InvocationOnMock invocation) throws Throwable
{
Record record = (Record) invocation.getArguments()[0];
Assert.assertEquals("F", record.getRecordStatus());
return record;
}
});
Record record = new Record();
record = recordService.save(record);
Assert.assertNotNull(record);
Mockito.verify(recordRepository, Mockito.times(1)).save(Mockito.eq(record));
}
#Test
public void findAll()
{
Mockito.when(recordRepository.findAll()).thenReturn(new ArrayList<Record>());
List<Record> records = recordService.findAll();
Assert.assertNotNull(records);
Assert.assertEquals(0, records.size());
Mockito.verify(recordRepository, Mockito.times(1)).findAll();
}
}
Test Class Configuration
#Configuration
public class RecordServiceTestConfig
{
#Bean
public RecordService recordService()
{
return new RecordServiceImpl();
}
#Bean
public RecordRepository recordRepository()
{
return Mockito.mock(RecordRepository.class);
}
}
the entire test class took 714ms to run the findAll test took 1ms.
If you are looking to configure your testcase using testng with Spring then you to mention
#ContextConfiguration(locations={
"/context.xml","/test-context.xml"})
at class level to load you spring file and extends your class org.springframework.test.context.testng.AbstractTestNGSpringContextTests
Sample
https://dzone.com/articles/spring-testing-support-testng
I'm new to Testing side.I'm using Spring Mvc in my application. I followed some tutorials to write for controller and service Test Case. I'm facing error in service test. Please help !
Service :
#Autowired
private PatientDao patientDao;
#Autowired
private PrefixDao prefixDao;
public Patient createPatient(Patient patient) throws Exception {
patient.setAgeorDob();
return createPatientInSync(patient);
}
private synchronized Patient createPatientInSync(Patient patient)
throws Exception {
try {
Prefix prefix = prefixDao.getPrefixForType(PrefixType.PATIENT);
patient.setPatientNo(prefix.getPrefixedNumber());
patientDao.createPatient(patient); //SAVE PATIENT
prefixDao.incrementPrefix(prefix);
} catch (ConstraintViolationException ex) {
throw new InternalErrorException("Please enter valid data", ex);
} catch (NullPointerException e) {
e.printStackTrace();
throw new InternalErrorException(
"Please create Prefix for Patient", e);
}
return patient;
}
Service Test case:
#ContextConfiguration(locations = {
"classpath:/applicationContext-resources.xml",
"classpath:/applicationContext-service.xml",
"classpath:/applicationContext-dao.xml",
"classpath:/applicationContext.xml" })
#RunWith(SpringJUnit4ClassRunner.class)
public class PatientServiceTest {
#Autowired
#Mock
private PatientDao patientDao;
#InjectMocks
private PatientServiceImpl patientService = new PatientServiceImpl();
private PrefixDao prefixDao;
#Before
public void doSetup() {
patientDao = mock(PatientDao.class);
prefixDao = mock(PrefixDao.class);
// Mockito.mock(PatientDao.class);
}
#Before
public void initMocks() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testSaveUser() throws Exception {
Patient mockPatient = new Patient();
mockPatient.setFirstName("Aravinth");
mockPatient.setSex(Gender.Male);
mockPatient.setAgeOrDob("24");
Prefix prefix = new Prefix();
prefix.setPrefixType(PrefixType.PATIENT);
prefix.setPrefix("Pat-");
prefix.setSequenceNo(23);
when(prefixDao.getPrefixForType(PrefixType.PATIENT)).thenReturn(prefix);
System.out.println(prefix.getSequenceNo());
mockPatient = patientService.createPatient(mockPatient);
assertEquals("Aravinth", mockPatient.getFirstName());
verify(patientDao, times(1)).createPatient(mockPatient);
}
}
Verify times works fine.I got Nullpointer in assertEquals.
Need to #Mock PrefixDao first.
If you are using Junit 5, no need to run initMocks(this). Otherwise you need this: MockitoAnnotations.initMocks(this);
With that, the mockito will wire two mock Dao objects to your service.
Also I don't see you mock action for patientDao.
When(patientDao.create()).thenReturn(...);