getAnnotation(Class<T>) always returns null when I'm using EasyMock/PowerMock to mock java.lang.reflect.Method - junit

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.

Related

Null pointer exception in method that calls another method Mockito

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.

Mockito is calling real method and thenReturn does not work

I have read some post about it but nothing solved my problem. I have a class which is singleton and one method of this class is being called inside another class. I need to mock this method call.
Class SingletonClass
{
public static SingletonClass instance()
{
......
return instance;
}
public boolean methodToBeMocked(Object obj)
{
return false;
}
}
And the another class is :
Class A
{
Object doSomeStuff()
{
......
boolean result = SingletonClass.instance.methodToBeMocked();
}
}
And I am mocking the method methodToBeMocked in my test class. I have tried to use doReturn instead of thenReturn as it is suggested in other posts but it did not help.
My test class is :
Class TestClass{
Class A a = new A();
public void test()
{
SingletonClass singletonClass = mock(SingletonClass.class);
doReturn(true).when(singletonClass).methodToBeMocked(any());
a.doSomeStuff(); // here mocked method returns false
// but if I do this below it returns true !!!!
Object obj = new Object();
boolean result = singletonClass.mockedMethod(obj);
}
}
So why I am not getting true when a.doSomeStuff is called ? What is wrong here ?
For the benefit of others, I was using the following mock with the expectation it would not call someMock.someMethod(), unlike the when(someMock.someMethod()).doReturn("someString") usage.
Mockito.doReturn("someString").when(someMock).someMethod();
I could not understand why the real someMethod() was still being called. It turns out the method was specified as final. Mockito can't mock static or final methods.
The problem is the static method public static SingletonClass instance(). The standard mockito library does not support mocking of static methods. I seen two solutions.
You can rewrite small your code as:
Add new method getSingletonClassInstance() to be mocked in test
Class A {
Object doSomeStuff()
{
......
boolean result = getSingletonClassInstance();
}
SingletonClass getSingletonClassInstance(){
return SingletonClass.instance.methodToBeMocked();
}
}
use spy from mockito library to create an instance of Class A
import static org.mockito.Mockito.spy;
.....
Class TestClass{
public void test()
{
Class A a = spy(new A());
SingletonClass singletonClass = mock(SingletonClass.class);
doReturn(true).when(singletonClass).methodToBeMocked(any());
doReturn(singletonClass).when(a).getSingletonClassInstance();
a.doSomeStuff(); // here mocked method returns false
// but if I do this below it returns true !!!!
Object obj = new Object();
boolean result = singletonClass.mockedMethod(obj);
}
}
More information about the spy in mockito. Spy used real instance and invoke real method but provide a functionality to mock specific method. Don't worry about the others method they will continue to work with real implementation, only mocked method will be affected.
You can use power mockito to mock the public static SingletonClass
instance()

Can any one help me in mocking a static method which returns an object, and this static method is present in a final class

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.

mock a method call with dynamic parameter

I have a method as follows
private void validate(String schemaName){
....
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);**strong text**
Source schemaFile = new SteamSource(getClass().getClassLoader().getResourceAsStream(schemaName));
Schema schema = factory.newSchema(schemaFile);
....
}
This method get called from another method which I need to test(Using easymock and powermock). I'm struggling to mock following line
Source schemaFile = new SteamSource(getClass().getClassLoader().getResourceAsStream(schemaName));
Can someone give me a clue on this?
Current Status
Following is the mock statement
expectNew(StreamSource.class, anyObject(InputStream.class)).andReturn(mockedobject);
Powermock.replay(mockedobject, StreamSrouce.class);
This throws the following exception.
org.powermock.reflect.exceptions.TooManyConstructorsFoundException: Several matching constructors found, please specify the argument parameter types so that PowerMock can determine which method you're referring to.
Matching constructors in class javax.xml.transform.stream.StreamSource were:
I think you can do it using powermock in the following way (I'm just following the tutorial here):
Let's say you're class looks like this:
public class MyClass {
private void validate(String schemaName) {
....
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);**strong text**
Source schemaFile = new SteamSource(getClass().getClassLoader().getResourceAsStream(schemaName));
Schema schema = factory.newSchema(schemaFile);
....
}
}
You should create a test class like this:
#RunWith(PowerMockRunner.class)
#PrepareForTest(MyClass.class)
public class MyClassTest {
private MyClass testedClass = new MyClass();
private ClassLoader mockedClassLoader = createMock(ClassLoader.class);
private InputStream mockedInputStream = createMock(InputStream.class);
#Before
public void setUp() {
PowerMock.createPartialMock(MyClass.class, "getClass");
expect(testedClass.getClass()).andReturn(mockedClassLoader);
expected(mockedClassLoader.getResourceAsStream(***You string***)).andReturn(mockedInputStream);
replayAll(); // Not sure if that's the name of the method - you need to call replay on all mocks
}
#Test
public void testValidate() {
// Run your test logic here
}
}
Please excuse me if some of the easymock methods I used are named a bit differently. But this is the basic idea.
I think you need one or a combination of the following. Use Powermock constructor mocking for the new StreamSource as documented here: Powermock MockConstructor. You will probably also need to use a mock for SchemaFactory which mean you will need to mock the static factory method call via Powermock: MockStatic

Apache Camel Integration Test - NotifyBuilder

I am writing integration tests to test existing Routes. The recommended way of getting the response looks something like this (via Camel In Action section 6.4.1):
public class TestGetClaim extends CamelTestSupport {
#Produce(uri = "seda:getClaimListStart")
protected ProducerTemplate producer;
#Test
public void testNormalClient() {
NotifyBuilder notify = new NotifyBuilder(context).whenDone(1).create();
producer.sendBody(new ClientRequestBean("TESTCLIENT", "Y", "A"));
boolean matches = notify.matches(5, TimeUnit.SECONDS);
assertTrue(matches);
BrowsableEndpoint be = context.getEndpoint("seda:getClaimListResponse", BrowsableEndpoint.class);
List<Exchange> list = be.getExchanges();
assertEquals(1, list.size());
System.out.println("***RESPONSE is type "+list.get(0).getIn().getBody().getClass().getName());
}
}
The test runs but I get nothing back. The assertTrue(matches) fails after the 5 second timeout.
If I rewrite the test to look like this I get a response:
#Test
public void testNormalClient() {
producer.sendBody(new ClientRequestBean("TESTCLIENT", "Y", "A"));
Object resp = context.createConsumerTemplate().receiveBody("seda:getClaimListResponse");
System.out.println("***RESPONSE is type "+resp.getClass().getName());
}
The documentation is a little light around this so can anyone tell me what I am doing wrong with the first approach? Is there anything wrong with following the second approach instead?
Thanks.
UPDATE
I have broken this down and it looks like the problem is with the mix of seda as the start endpoint in combination with the use of a recipientList in the Route. I've also changed the construction of the NotifyBuilder (I had the wrong endpoint specified).
If I change the start endpoint to
direct instead of seda then the test will work; or
If I comment out the recipientList
then the test will work.
Here's a stripped down version of my Route that reproduces this issue:
public class TestRouteBuilder extends RouteBuilder {
#Override
public void configure() throws Exception {
// from("direct:start") //works
from("seda:start") //doesn't work
.recipientList(simple("exec:GetClaimList.bat?useStderrOnEmptyStdout=true&args=${body.client}"))
.to("seda:finish");
}
}
Note that if I change the source code of the NotifyTest from the "Camel In Action" source to have a route builder like this then it also fails.
Try to use "seda:getClaimListResponse" in the getEndpoint to be sure the endpoint uri is 100% correct
FWIW: It appears that notifyBuilder in conjunction with seda queues are not quite working: a test class to illustrate:
public class NotifyBuilderTest extends CamelTestSupport {
// Try these out!
// String inputURI = "seda:foo"; // Fails
// String inputURI = "direct:foo"; // Passes
#Test
public void testNotifyBuilder() {
NotifyBuilder b = new NotifyBuilder(context).from(inputURI)
.whenExactlyCompleted(1).create();
assertFalse( b.matches() );
template.sendBody(inputURI, "Test");
assertTrue( b.matches() );
b.reset();
assertFalse( b.matches() );
template.sendBody(inputURI, "Test2");
assertTrue( b.matches() );
}
#Override
protected RouteBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
#Override
public void configure() throws Exception {
from(inputURI).to("mock:foo");
}
};
}
}