Powermockito: mocking static method - java

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 .

Related

How to cover the Class instantiated inside a method in Mockito Junit?

How can I cover the class instantiated inside a method and need to get the value that is not set.
Here is my Service class DemoClass.Java
public class DemoClass{
public void methodOne(){
ClassTwo classTwo=new ClassTwo();
classTwo.setName("abc");
customerRepo.save(classTwo);
ClassThree classThree=new ClassThree();
classThree.setId(classTwo.getId()); //here causing NullPointerException as ClassTwo is instantiated inside the method and the id value is not set and the test stops here.
classThree.setName("person1");
classThree.setUpdatedBy("person2");
}
}
As the classTwo is instantiated in the method level the test method does not get the getId(). And I can't change or add anything to the Controller class. The test stops at that line and causing NullPointerException as it doesn't know the value classtwo.getId() as it is not set. I need to cover that/ pass that line in the test class.
I tried mocking that class and spy also. Any Mockito solutions available for this.
The Id in ClassTwo is an autogenerated sequence number so no need of setting in DemoClass.Java
Here is my test class DemoClassTest.Java
#RunWith(MockitoJunitRunner.Silent.class)
public void DemoClassTest(){
#InjectMocks
DemoClass demoClass;
#Test
public void testMethodOne(){
demoClass.methodOne()
}
You could provide a customerRepo test double that just sets some specific id on classTwo:
public class TestCustomerRepo extends CustomerRepo {
public void save(ClassTwo classTwo) {
classTwo.setId(4711L);
}
}
But since you seem to be testing JPA code it would probably be a better idea to perform an integration test containing an actual database instead.
I usually do it like this:
long testId = 123;
Mockito.when(customerRepo.save(Mockito.any())).thenAnswer(invocation -> {
ClassTwo entity = (ClassTwo)invocation.getArgument(0);
entity.setId(testId);
return entity;
});
If you want to assert something on the ClassThree entity, do a Mockito.verify on the ClassThree repository mock.

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

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.

What is a good practice for creating test case in a class where one function calls other function of same class in Mockito?

I have a Util.java class which contains some functions as follows:
public Util {
UtilB b;
funcA() {
//someAction
String a = b.someMethod();
funcB();
}
funcB() {
//recursive call to funcB
funcC();
}
funcC() {
//some processing
}
}
While writing test case in Mockito, I did something as follows:
public UtilTest {
#Mocks
UtilB b;
#InjectMocks
Util test;
#Test
public funcA() {
when(b.someMethod()).thenReturn("");
test.funcA();
}
}
As can be seen above, I cannot mock a call to funcB() when funcA() is called. The call will go inside funcB(). I can shift funcB() in another class like someMethod() in UtilB and mock that class like UtilB b and the test will work without actually calling funcB(), but is that a good practice to go on about creating new classes?
Additionally, since I am testing class Util, it should not be good to make it a spy and then operate on it to mock a call to funcB() right?
Should I even Mock funcB() in the first place since test.funcA() will cover funcB() and funcC() as well?
Could someone please guide me what is a good practice in this scenario?

Mocking a static method which calls another static method of the same class

I have to write a unit test for a static method which requires mocking another static method of the same class.
Sample code:
public class A {
public static boolean foo(){}
public static boolean bar(){
return foo();
}
}
#PrepareForTest({A.class})
public ATest{
testMethod(){
mockStatic(A.class);
when(A.foo()).thenReturn(true);
assertTrue(A.bar());
}
}
I have been trying to unit test the bar method but so far not been successful.
Issue: Debug doesn't reach the return foo(); statement in my code and assertion fails. Please advice. I cannot modify the code at this point of time
Any help in mocking the foo method would be appreciated.Thanks!
In this scenario, you should not be creating a mock on class but use stub on only that particular method ( foo() ) from class A,
public static <T> MethodStubStrategy<T> stub(Method method)
Above method belongs to MemberModifier class in API and that is a super class of PowerMockito class so your syntax should look like,
PowerMockito.stub(PowerMockito.method(A.class, "foo")).toReturn(true);
The fact that false is the default value for boolean played a bad trick. You were expecting that wrong foo is called, while in fact bar was not called. Long story short:
when(A.bar()).thenCallRealMethod();

Mocking - zero interactions

I have written a test to verify that a public method in my class is called. My test is failing as follows. Can anyone tell me why this happening?
Wanted but not invoked: `mockMyClass.runThis();
Actually, there were zero interactions with this mock.
class MyClass{
public void myMethod(){
runThis("hello");
}
}
public void runThis(String str){
return;
}
Test class
#Mock
MyClass mockMyClass;
MyClass myClass = new MyClass();
#Test
public void test(){
myClass.myMethod();
verify(mockMyClass).runThis(anyString());
}
You're not invoking against your mock, but rather the real class. You need to generate a mock, and then invoke on that mock. Try something like:
MyClass mock = mock(MyClass.class); // I'm using the methods rather than annotation here
mock.myMethod();
and assert on that. I'm not quite sure in the above where runThis() is, though. If it's on a contained class, then that's the thing to need to mock. If it's on the same class, then you can't use a mock per se, since the mock substitutes all functionality, and perhaps the Mockito spy() mechanism would be of use here. Section 13 of the doc advises more on this.

Categories