Using PowerMockito to mock a class with #Inject variables and static methods - java

I am trying to use a power mock to mock a class with #Injects and static methods called in another class constructor. But for some reason it seems to be throwing MissingMethodInvocationException in PowerMockito.when.
#Named
public class InstanceLocationWrapperFactory {
#Inject
private InstanceLocation instanceLocation;
private static InstanceLocation internalInstanceLocation;
#PostConstruct
private void load(){
internalInstanceLocation = instanceLocation;
}
public static InstanceLocation getInstance(){
return internalInstanceLocation;
}
}
I am trying to use it to instantiate a value inside the constructor of another class like as follows. (InstanceLocation is a interface which is implemented by DefaultInstanceLocationImpl class.)
class A{
InstanceLocation instance;
A(){
instance = InstanceLocationWrapperFactory.getInstance();
}
public String myMethod(){
/* using instance here to do some logic*/
}
}
I am trying to write a test like this
#RunWith(PowerMockRunner.class)
#PrepareForTest({A.class, InstanceLocationWrapperFactory.class})
public class ATest {
#Test
public void myTestCase1{
InstanceLocation instanceLocation = mock(DefaultInstanceLocationImpl.class);
PowerMockito.mockStatic(InstanceLocationWrapperFactory.class);
PowerMockito.when(InstanceLocationWrapperFactory.getInstance()).thenReturn(instanceLocation);
when(instance.getMethod()).thenReturn("something");
}
But when i run the above code for some reason i keep getting the below error for the line PowerMockito.when(InstanceLocationWrapperFactory.getInstance()).thenReturn(instanceLocation);.
org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.
Can someone please help me understand if I am doing something wrong or missing something here.

Related

Mocking static method in Java

Is there way to mock for unit test static method in Java without executing the method actual implementation? Actual implementation launches the process that cannot be done in unit test context.
public class MyExecutor {
public static int execute(...) {
Process pr = Runtime.getRuntime().exec(...)
int status = pr.waitFor();
return status;
}
public MyClass {
public void methodToUnitTest(...){
MyExecutor.execute(...)
}
I want to mock MyExecutor.execute and verify both its invocation and its params when unit testing MyClass.methodToUnitTest but without actual execution of this method.
I read that PowerMockito can mock static method but it does not prevent actual implementation from being executed.
Wrap the static class MyExecutor in a non-static class. Extract the methods of your new non-static class into an interface. Replace the dependencies to static class with the interface - use dependency injection to provide MyExecutor instances to MyClass:
public MyExecutorAdapter implements Executor{
public void execute() {
MyExecutor.execute() //call to static code
}
}
public MyClass {
private Executor myExecutor;
public MyClass(Executor myExecutor){ //MyExecutorAdapter instance can be injected here
this.myExecutor = myExecutor;
}
public void methodToUnitTest(...){
myExecutor.execute(...)
}
}
Now, with the interface, you can easily mock or provide a fake implementation for testing purposes. In your case, you probably need to have a mock to check if the execute method was called.
This is basically known as Adapter pattern

Mocking method calls in a different class apart from test class without PowerMock

I am having some trouble writing a unit test for my application. Currently, I am testing class A. In the method of class A I am testing, it makes a call to a helper class's method, which then calls another method inside the same helper class(getKeyObject) whose only function is to call a static method of a class contained in a framework I am using(buildKeyObject()). I am trying to stub getKeyObject() so that it returns a mock of the Object that is normally generated, but I have no idea on how to proceed.
One way I thought was to utilize PowerMockito and use PowerMockito.mockStatic(ClassInFramework.class) method to create a mock of the class in the framework I am using, and then use when(ClassInFramework.buildKeyObject()).thenReturn(KeyObjectMock), but due to some limitations on the work I am doing, I am forbidden to use PowerMockito. I am also unable to use Mockito.spy or the #spy annotation because of the same reasons.
class ATest{
public A aInstance = new A();
#Test
public void test(){
KeyObject keyObjectMock = Mockito.mock(KeyObject.class);
/*
between these 2 lines is more mockito stuff related to the KeyObjectMock above.
*/
String content = aInstance.method1();
Assert.assertEquals(content, "string")
}
}
class A{
public RandomClass d = new RandomClass()
public String method1(){
Helper helper = new Helper();
Object a = helper.method2()
return d.process(a);
}
}
class Helper{
public Object method2(){
KeyObject keyObject = getKeyObject();
Object object = keyObject.getObject();
return object;
}
public KeyObject getKeyObject(){
return ClassInFramework.buildKeyObject(); //static method call.
}
}
Can you guys help me with this?
Constructor injection is one of the common ways to do this. It does require you to modify the class under test for easier testing.
First, instead of creating a new Helper in the method, make it a member variable and assign it in the constructor.
class A {
private Helper helper;
// constructor for test use
public A(Helper helper) {
this.helper = helper;
}
// convenience constructor for production use
public A() {
this(new Helper());
}
}
Now, in your test, you can use the test constructor to inject any mock object derived from Helper. This can be done using Mockito or even simple inheritance.
class MockHelper extends Helper {
// mocked methods here
}
class ATest {
public A aInstance = new A(new MockHelper());
// ...
}

Powermock invokes initial method when trying to mock static method call within static method call

Is there any reason why Powermock wouldn't mock static method call and instead call the initial method within then() statement?
Here's the case where I have a chain of method calls:
TestClass method -call-> Class1 method -call-> Class2 static method -call-> Class3 static method -call-> Class4 method.
Class4 method tries to lookup an object that doesn't exist in context and hangs so I'm trying to mock public static Class3 method with Powermock.
All classes and methods are non-final.
I use TestNg. My testMethod has a #PrepareForTest
I tried the following ways to mock a method call:
PowerMockito.mockStatic(Class3.class);
when(Class3.callEvilMethod()).thenReturn("test");
OR instead of when-thenReturn:
doReturn("test").when(Class3.callEvilMethod());
OR
doAnswer(new Answer() {methos that returns test"}).when(Class3.callEvilMethod());
OR
PowerMockito.stub(PowerMockito.method(Class3.class, "callEvilMethod")).toReturn("test");
But when I run tests the initial Class3.callEvilMethod() gets called within when statement. And I have no idea why. Shouldn't it be mocked?
EDIT: I adapted my test to show you how it looks like:
#PrepareForTest( { Class1.class, Class2.class, Class3.class})
public class TestClass extends AbstractTest {
private Class1 class1;
#BeforeMethod
public void setUp() throws Exception {
class1 = new Class1() {
}
#Test
public void testMethod() throws Exception {
// Create various objects in Db, do other method calls, then:
PowerMockito.mockStatic(Class3.class);
// PowerMockito.suppress(PowerMockito.method(Class3.class, "evilMethod"));
// PowerMockito.when(Class3.EvilMethod()).thenReturn("test");
// doReturn("test").when(Class3.evilMethod());
// PowerMockito.stub(PowerMockito.method(Class3.class, "evilMethod")).toReturn("test");
class1.callMethod();
}
}
Ok what is supposed to fix the problem and was missing in my test is either:
#ObjectFactory
public IObjectFactory setObjectFactory() {
return new PowerMockObjectFactory();
}
or simply sublcassing from PowerMockTestCase
Details

Mocking static methods with jmockit (1.5) before class

According to the example in the Jmockit tutorial this code should do the trick:
#BeforeClass
public static void setUpClass() {
new MockUp<UtilJndi>(){
#Mock
public static String getDirectoryFromContext(Property jndiName) // line 66
throws DirectoryNotFoundException {
return "noDirectory";
}
};
}
But it shows:
myclass.java:[66,29] error: Illegal static declaration
How can I resolve this?
I will add another workaround wich works for me:
I create my mocked class extending MockUp:
public static class MockUtilJndi extends MockUp<UtilJndi> {
public MockUtilJndi() {
super();
}
#Mock
public static String getDirectoryFromContext(Property jndiName)
throws DirectoryNotFoundException {
return "noDirectory";
}
}
If you notice I call the super() inside my constructor. Cause according to documentation if you call MockUp constructor it will change the implementation in the target class.. so once you have this in your mocked class constructor you just need to create your class inside the #BeforeClass annotated method:
#BeforeClass
public static void setUpClass() {
new MockUtilJndi();
}
Ok, I will update my comment to an answer.
First, the error message is very clear. "Illegal static declaration" just means, that the static keyword is placed wrong. Remove it!
As you are trying to mock a static method, you might have believed that you must put the static keyword also. But the documentation for the Mock annotation says:
Method modifiers (including public, final, and even static), however, don't have to be the same.
That simply means, you can mock static methods even without declaring it static.
Hmm ... I strongly feel, that the documentation's wording is a bit confusing. Obviously, it is not an option, but you must not declare it static.

Powermockito: mocking static method

I am mocking a static method as follows:
class A{
static String methodA(HashMap<String,Boolean> h){
...
Set<String> keys=h.entrySet();
}
}
Powermockito code:
Powermockito.mockstatic(A.class);
when(A.methodA(any(HashMap.class)).thenReturn("Hey");
Now, when I do not expect a call to methodA to enter the function definiton, but directly return "hey". However, this is not happening. Despite the mock, the call to methodA() enters it, and since I am passing any(HashMap.class), a null value is passed. I get a NullPointerException. What am I doing wrong?
You need to have following on top of your class:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ A.class})
class ATest {
....
}
The annotation #RunWith, indicates that PowerMockRunner is to be used for executing the test case. Any class which requires static or private methods to be mocked, goes into #PrepareForTest, in this case : class A .

Categories