I am new to Mockito and Powermockito. I have a class to test which interacts with the database in order find and also delete data from the database through different public methods. The application is typical Java EE application and the The class under test belongs to Service package in Businesslogic. The method which I want to test looks like below :
public List<QuestionDtoWrapper> searchInQuestions(final Integer ID, final Integer catID,
final String searchString, final String language) {
final List<QuestionDtoWrapper> result = new ArrayList<>();
//In line below I get null pointer exception although I have stubbed this method
final List<QuestionDtoInt> questions = facade.findQuestionsByCatTemplate(ID, catID,
searchString, language);
for (final QuestionDtoInt question : questions) {
result.add(new QuestionDtoWrapper(question));
}
Collections.sort(result, new QuestionComparator(new Locale("de")));
return result;
}
This is how I tried to test the method in my Junit Test:
#RunWith(MockitoJUnitRunner.class)
#PrepareForTest(QuesService.class)
public class QuesServiceTest {
#Mock
QuesFacade mockFbFacade;
#Mock
List<QuesDtoInt> questions;
#Spy
QuesService myService = new QuesService();
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
#Test
public void testSearchInQuestions() throws ParseException {
PowerMockito.doReturn(questions).when(mockFbFacade).findQuestionsByCatTemplate(anyInt(), anyInt(), anyString(), anyString());
List<QuestionDtoWrapper> res = null ;
res = myService.searchInQuestions(anyInt(), anyInt(), anyString(), anyString());
assertNotNull(res);
}
I am getting Null pointer exception in Line where the method calls another method. See my comment in source code. Could someone please let me know:
1) Am I using mockito for the correct subject ? Should I use real Test data ? But what about the database connections n all ? I tried that approach and ended up using Mockito only.
2) Why am I getting Null pointer exception although I have stubbed that method with Powermockito ?
3) please provide your valuable suggestions to test the given method correctly.
Note:- I am not allowed to do any refactoring in the code.
Related
I have DAO class as below:-
// Here I have a class that creates it's own jdbcTemplate using new
// jdbcTemplate(dataSource)
#Repository
public class MyDao {
#Autowired
#Qualifier("db2JdbcTemplate)"
JdbcTemplate jdbcTemplateDB2;
public int insertTable(Company comp) {
int ret = 0;
try {
ret = this.jdbcTemplateDB2(db2DataSource).update(ïnsert into "+ table_name + "(COL1,COL2,...) values (?,?,?,..)",
ps-> {
ps.setString(1, comp.getName);
.......
});
return ret;
} catch (Exception ex) {
// log etc
}
}
}
My Test class is as below:-
#RunWith(MockitoJUnitRunner.class)
public class MyTest {
#Mock
JdbcTemplate jdbcTemplateDB2;
Company comp = new Company(); // this is followed by setter fn to set values.
MyDao mydao = Mockito.mock(MyDao.class);
Mockito.when(((jdbcTemplateDB2.update(any(String.class),
any(PreparedStatement.class))).thenReturn(2);
ReflectionUtils.setField(mydao, "jdbcTemplateDB2", jdbcTemplateDB2);
int bVal = mydao.insertTable(cmp);
}
}
iVal is not getting value 2. It is making original update call and returning value like 0/1.
Getting UnnecessaryStubbingException. If I make lenient() call the exception goes away but result is same (expected as lenient only removes warning).
How to make this stubbing work?
In this line: MyDao mydao = Mockito.mock(MyDao.class); you're creating a mock object, which overrides your actual class'x behavior, but you seem to want to test this very class, so it doesn't make any sense. What you need to do is: create an actual instance of the class and inject mocks into it (you're using ReflectionUtils to do that, but Mockito has it's own, simple mechanism to do that).
#Mock
JdbcTemplate jdbcTemplateDB2;
// this tells mockito to create the object and inject mocks into it
#InjectMocks
MyDao myDao;
#Test
void test() {
// define the behavior for the mock
when(jdbcTemplateDB2.update(...)).thenReturn(2);
// call the actual method of the tested class object (not a mock)
int result = myDao.insertTable(...);
// perform assertions (e.g. verify the result value)
}
Recommended reading: Mockito documentation (very comprehensive, yet simple).
Important note: field injection is discouraged.
I need help for below thing,
I have to write a Junit using PowerMock/Mockito for a method which makes a call to a static method of a final class present in an external jar.
The method for which i need to write the JUnit test is:
public class SomeClass {
private PrivateKey privateKeyFromPkcs8(String privateKeyPem) throws IOException {
Reader reader = new StringReader(privateKeyPem);
Section section = PemReader.readFirstSectionAndClose(reader, "PRIVATE KEY");
if (section == null) {
throw new IOException("Invalid PKCS8 data.");
}
byte[] bytes = section.getBase64DecodedBytes();
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes);
try {
KeyFactory keyFactory = SecurityUtils.getRsaKeyFactory();
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
return privateKey;
} catch (NoSuchAlgorithmException exception) {
} catch (InvalidKeySpecException exception) {
}
throw new IOException("Unexpected exception reading PKCS data");
}
}
In the above code PemReader is a final class and readFirstSectionAndClose(reader, "PRIVATE KEY") is a static method in PemReader.
I have tried writing the test shown below but Section object(section) is showing as null while debugging. Perhaps the actual code (PemReader.readFirstSectionAndClose(reader, "PRIVATE KEY")) is getting called instead of the mock.
#RunWith(PowerMockRunner.class)
#PrepareForTest({SomeClass.class,PemReader.class})
public class SomeClassTest {
#InjectMocks
SomeClass mockSomeClass;
#Mock
private Reader mockReader;
#Mock
private Section mockSection;
#Test
public void testPrivateKeyFromPkcs8() throws Exception {
PowerMockito.mockStatic(PemReader.class);
Mockito.when(PemReader.readFirstSectionAndClose(mockReader, "PRIVATE KEY")).thenReturn(mockSection);
assertNotNull(mockSomeClass.privateKeyFromPkcs8(dummyPrivateKey));
}
}
Please help me in writing a Junit using powermockito/mockito
You have to prepare the final, static class.
Here's an example using the PowerMock annotations for JUnit:
#RunWith(PowerMockRunner.class)
#PrepareForTest({PemReader.class})
public class PemReaderTest {
#Mock
private Reader mockReader;
#Mock
private Section mockSection;
#Test
public void testMockingStatic() {
PowerMockito.mockStatic(PemReader.class);
Mockito.when(PemReader.readFirstSectionAndClose(mockReader, "PRIVATE KEY")).thenReturn(mockSection);
Assert.assertEquals(mockSection, PemReader.readFirstSectionAndClose(mockReader, "PRIVATE KEY"));
}
}
For completeness, here's the definition of PemReader:
public final class PemReader {
public static Section readFirstSectionAndClose(Reader reader, String key) {
return null;
}
}
The above test passes with the following versions:
JUnit: 4.12
Mockito: 2.7.19
PowerMock: 1.7.0
Update 1: based on your updated question. Your test case will pass (or at least the invocation on PemReader.readFirstSectionAndClose will return something) if you just make this change:
Mockito.when(PemReader.readFirstSectionAndClose(
Mockito.any(Reader.class),
Mockito.eq("PRIVATE KEY"))
).thenReturn(mockSection);
The version of this instruction in your current test case relies on equality matching between the StringReader which your code passes into readFirstSectionAndClose and the mocked Reader which your test case supplies. These are not 'equal' hence the mocked invocation's expectations are not met and your mockSection is not returned.
A few, unrelated, notes:
There is no need to include SomeClass.class in #PrepareForTest, you only need to include the classes which you want to mock in that annotation, since SomeClass is the class you are trying to test there is no mocking required for that class.
Using #InjectMocks to instance SomeClass is a bit odd, since SomeClass has no (mockito provided) mocks to inject into it :) you can replace this declaration with SomeClass someClass = new SomeClass();
In the code you supplied SomeClass.privateKeyFromPkcs8 has private scope so it cannot be tested (or called in any way) from SomeClassTest.
The tested method has the following code:
SuppressWarnings suppressWarnings = method.getAnnotation(SuppressWarnings.class);
In my test method.I mocked java.lang.reflect.Method:
Method method= PowerMock.createMock(Method.class);
SuppressWarnings sw = EasyMock.createMock(SuppressWarnings.class);
EasyMock.expect(method.getAnnotation(SuppressWarnings.class)).andReturn(sw);
In the tested method,
method.getAnnotation(SuppressWarnings.class); always returns null.
I don't know why.Could anyone help me?
//code:
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface Anonymous {
}
public class AnnotationClass {
public Anonymous fun(Method m){
Anonymous anonymous = m.getAnnotation(Anonymous.class);
return anonymous;
}
}
// test class:
#RunWith(PowerMockRunner.class)
#PrepareForTest(Method.class)
public class AnnotationClassTest {
#Test
public void test() throws NoSuchMethodException, SecurityException {
AnnotationClass testClass = new AnnotationClass();
final Method mockMethod = PowerMock.createMock(Method.class);
final Anonymous mockAnot = EasyMock.createMock(Anonymous.class);
EasyMock.expect(mockMethod.getAnnotation(Anonymous.class)).andReturn(mockAnot);
PowerMock.replay(mockMethod);
final Anonymous act = testClass.fun(mockMethod);
Assert.assertEquals(mockAnot, act);
PowerMock.verify(mockMethod);
}
}
error:
java.lang.AssertionError: expected:<EasyMock for interface
com.unittest.easymock.start.Anonymous> but was:<null>
SuppressWarnings has #Retention(value=SOURCE) which means that it is not available at runtime:
public static final RetentionPolicy SOURCE: Annotations are to be discarded by the compiler.
However, if you would try your code with a different annotation that is available at runtime, method.getAnnotation(MyAnnotation.class) would still return null. That is, because by default the mocked Method will return null for method calls.
I think your problem is in the configuration of the mock, when I run your code (using an annotation that is available at runtime) I get the following exception:
Exception in thread "main" java.lang.IllegalStateException: no last call on a mock available
at org.easymock.EasyMock.getControlForLastCall(EasyMock.java:466)
at org.easymock.EasyMock.expect(EasyMock.java:444)
at MockStuff.main(MockStuff.java:54)
This page has some explanations about how to mock a final class (such as Method).
Your code gives the exact same result for me. I was able to get it working using the following code:
#RunWith(PowerMockRunner.class)
#PrepareForTest(Method.class)
public class AnnotationClassTest {
#Test
public void test() throws NoSuchMethodException, SecurityException {
final Method mockMethod = PowerMock.createMock(Method.class);
final Anot mockAnot = EasyMock.createMock(Anot.class);
EasyMock.expect(mockMethod.getAnnotation(Anot.class)).andReturn(mockAnot);
PowerMock.replay(mockMethod);
final Anot methodReturn = mockMethod.getAnnotation(Anot.class);
Assert.assertEquals(mockAnot, methodReturn);
}
}
#Retention(RetentionPolicy.RUNTIME)
#interface Anot {}
Note that this code is self contained, I defined the Anot interface since you didn't give the definition of Anonymous.
Hi i am trying to mock dao layer
my application has some class hire achy like this Application->parser->dao(interface)->dao implementation class
my problem is when i am mocking dao interface or daoimp class using mockito
in my test case they are not working simply test case going to db how to do make our test case to use these mocked objects
#RunWith(MockitoJUnitRunner.class)
public class CsvDataLoadServiceImplTest {
#Mock private MeteringDataDao meteringDataDao;
List<Object> persistedList;
Object meteringData;
List<Object> s=new ArrayList<Object>();
#SuppressWarnings({ "rawtypes", "unchecked" })
#Before public void setup(){
Mockito.doAnswer(new Answer<List<Object>>() {
#Override
public List<Object> answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
System.out.println("persist all");
if(persistedList == null){
persistedList = (List)args[0];
}
else
persistedList.addAll((List)args[0]);
return null;
}}).when(meteringDataDao).persistAll(anyList());
Mockito.doAnswer(new Answer<Object>() {
#Override
public Object answer(InvocationOnMock invocation) {
Object[] args = invocation.getArguments();
if(meteringData == null)
meteringData = (List)args[0];
return true;
}}).when(meteringDataDao).persist(anyObject());
}
#After public void tearDown(){
persistedList = null;
meteringData = null;
}
#Test
public void testDataAccuricy(){
CsvDataLoadService csvDataLoadService =new CsvDataLoadServiceImpl();
csvDataLoadService.loadRackspaceCsvData();
}
}
CsvDataLoadService csvDataLoadService = new CsvDataLoadServiceImpl();
You're constructing an instance of the service, but this instance doesn't use the DAO you mocked. It uses another one. You need something like
CsvDataLoadService csvDataLoadService =
new CsvDataLoadServiceImpl(meteringDataDao);
Your question is a little badly phrased, so sorry if I appear to have misunderstood you.
#JBNizet answer is correct, you're not using the mocked object, but rather than changing the code for a test you should simply change the test. This is always a best practice when writing your tests.
You haven't assigned the mocked object to the service, so I'm assuming that the MeteringDataDao object is actually instantiated inside the class you're attempting to test?
If so, then you will need something more powerful than Mockito (Unless you want to reproduce the capabilities of a more powerful already existing library). I would suggest PowerMockito, which I have used in the past for something exactly like this.
A good example of using powermockito to mock the constructor of a class can be seen in a few answers on SO already, so I'll just link to them rather than try and re-explain their already clear answers:
Powermock constructor mocking has no effect on the instantiated object
mockito mock a constructor with parameter
I have a code that will be tested:
public void ackAlert(final Long alertId, final String comment) {
final AnyTask task = AnyTask.create(
"ackAlert", new Class[] { Long.class, String.class },
new Object[] { alertId, comment });
taskExecutor.execute(task);
}
I'm writting test to it:
public void testAckAlert() throws Exception {
final Long alertId = 1L;
final String comment = "tested";
final AnyTask task = AnyTask.create(
"ackAlert", new Class[] { Long.class, String.class },
new Object[] { alertId, comment });
taskExecutor.execute(task);
expectLastCall();
replay(taskExecutor);
testingObjectInstance.ackAlert(alertId, comment);
verify(taskExecutor);
}
And I got exception:
java.lang.AssertionError: Unexpected method call
execute(com.alert.bundle.model.AnyTask#4cbfea1d):
execute(com.alert.bundle.model.AnyTask#65b4fad5): expected: 1,
actual: 0
Where is my error? I think problem is in invocation of static method create.
It may not be important to mock your static method, depending on what it is that you want to test. The error is because it does not see the task that gets created in the method you are testing as equal to the task you passed to the mock.
You could implement equals and hashCode on AnyTask so that that they do look equivalent. You could also 'capture' the task being passed to execute and verify something about it after the test. That would look like this:
public void testAckAlert() throws Exception {
final Long alertId = 1L;
final String comment = "tested";
mockStatic(AnyTask.class);
Capture<AnyTask> capturedTask = new Capture<AnyTask>();
taskExecutor.execute(capture(capturedTask));
expectLastCall();
replay(taskExecutor);
testingObjectInstance.ackAlert(alertId, comment);
AnyTask actualTask = capturedTask.getValue();
assertEquals(actualTask.getName(), "ackAlert");
verify(taskExecutor);
}
If you are not really testing anything about the task, but just that the taskExecutor.execute() is called, you could simply replace
taskExecutor.execute(task);
with
taskExecutor.execute(isA(AnyTask.class));
or even
taskExecutor.execute(anyObject(AnyTask.class));
I don't see where you're creating your mocks, but yes, mocking a static method call can't be done with EasyMock alone. However, PowerMock can be used with either EasyMock or Mockito to mock a static method call.
You will need to annotate your test class with #RunWith(PowerMockRunner.class) and #PrepareForTest(AnyTask.class). Then your test would look something like this:
public void testAckAlert() throws Exception {
final Long alertId = 1L;
final String comment = "tested";
mockStatic(AnyTask.class);
final AnyTask task = new AnyTask();
expect(AnyTask.create(
"ackAlert", new Class[] { Long.class, String.class },
new Object[] { alertId, comment })).andReturn(task);
taskExecutor.execute(task);
expectLastCall();
replay(AnyTask.class, taskExecutor);
testingObjectInstance.ackAlert(alertId, comment);
verify(taskExecutor);
}