Static mocking with PowerMock and Mockito not working - java

I'm trying to verify that the Collections.shuffle() method was called in one of my classes. I read through the (little) documentation on PowerMock with Mockito and read through the other SO questions that dealt with this issue and didn't get a resolution.
#RunWith(PowerMockRunner.class)
#PrepareForTest(Collections.class)
public class MyTest {
#Test
public void testShuffle() {
PowerMockito.mockStatic(Collections.class);
PowerMockito.doCallRealMethod().when(Collections.class);
Collections.shuffle(Mockito.anyListOf(Something.class));
ClassToTest test = new ClassToTest();
test.doSomething();
PowerMockito.verifyStatic(); // Verify shuffle was called exactly once
Collections.shuffle(Mockito.anyListOf(Something.class));
}
}
public class ClassToTest {
private final List<Something> list;
// ...
public void doSomething() {
Collections.shuffle(list);
// do more stuff
}
}
Given the above code, I expect the unit test pass. However, the unit test fails as follows:
Wanted but not invoked java.util.Collections.shuffle([]);
Actually, there were zero interactions with this mock.
What am I doing wrong?
Thanks
EDIT:
As per the suggestion below I tried the following, and I get the same error.
#RunWith(PowerMockRunner.class)
#PrepareForTest(Collections.class)
public class MyTest {
#Test
public void testShuffle() {
PowerMockito.mockStatic(Collections.class);
ClassToTest test = new ClassToTest();
test.doSomething();
PowerMockito.verifyStatic(); // Verify shuffle was called exactly once
Collections.shuffle(Mockito.anyListOf(Something.class));
}
}

This is a rather old question, but I'd still like to clarify that the accepted answer is in fact incorrect. By executing the following code,
PowerMockito.mockStatic(Collections.class);
Collections.shuffle(Mockito.anyListOf(Something.class));
all verifies will always pass afterwards:
PowerMockito.verifyStatic(); // Verify shuffle was called exactly once
Collections.shuffle(Mockito.anyListOf(Something.class));
even if you do not call test.doSomething(); the provided test in the answer will still pass. The correct way to test this is to actually check if the items in the List have been sorted correctly.

You can either mock/verify the java.util.Collections.shuffle([]) method or call the real implementation (with PowerMockito.doCallRealMethod()). But you can't do both.
If you remove
PowerMockito.doCallRealMethod().when(Collections.class);
the call will be verified and the test will pass.
https://powermock.googlecode.com/svn/docs/powermock-1.4.7/apidocs/org/powermock/api/mockito/PowerMockito.html#doCallRealMethod%28%29
This code works for me:
package test;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest(Collections.class)
public class MyTest {
#Test
public void testShuffle() {
PowerMockito.mockStatic(Collections.class);
/* PowerMockito.doCallRealMethod().when(Collections.class); remove this line */
Collections.shuffle(Mockito.anyListOf(Something.class));
ClassToTest test = new ClassToTest();
test.doSomething();
PowerMockito.verifyStatic(); // Verify shuffle was called exactly once
Collections.shuffle(Mockito.anyListOf(Something.class));
}
}
class ClassToTest {
private List<Something> list = new LinkedList<Something>();
// ...
public void doSomething() {
Collections.shuffle(list);
// do more stuff
}
}
class Something {
}

Related

How to test a method of a class with constructor arguments using Mockito/Powermock

I have a Mockito/PowerMockito issue!
The class to test is as below :
public class ClassToTest {
private String string;
public ClassToTest(String s) {
this.string = s;
}
public String concatenate() {
return string.concat(" - Done!");
}
public ClassToTest create(String s) {
return new ClassToTest(s);
}
}
The test class i wrote :
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest(ClassToTest.class)
public class ClassToTestTest {
#Test
public void concatenate() throws Exception {
ClassToTest classToTest = Mockito.mock(ClassToTest.class);
PowerMockito.whenNew(ClassToTest.class).withArguments(Mockito.anyString()).thenReturn(classToTest);
classToTest.concatenate();
}
}
Question - How do i set a value of the instance variable named "string" from test class so that i can test concatenate method(concatenate method uses the constructor initialized "string" variable") Currently the debug point is not even going inside concatenate() method. I need to do this with either mockito/powermock.
Note - The example I have given is a representation of the issue i am facing in real time.
Any leads would help me.
Thanks in advance!!
Your test is pointless for several reasons.
you mock the class you're trying to test
you mock a method that is not even called in the test
you don't verify the result of the method you call.
Your test can just be
ClassToTest tested = new ClassToTest("test"); // create instance
String concatResult = tested.concatenate(); // call method under test
assertThat(concatResult).isEqualTo("test - Done"); // verify result
No need to mock anything. If you want to test the create method (of which I don't see the point at all btw), you can do
ClassToTest tested = new ClassToTest(""); // the String is never used anyway
ClassToTest created = tested.create("test"); // call method under test
assertThat(created.concatenate()).isEqualTo("test - Done"); // verify
If you mock classes you're testing, you don't test the classes behavior, but only the mocked result. Consider
Don't do this
ClassToTest mock = mock(ClassToTest.class);
ClassToTest other = mock(ClassToTest.class);
when(mock.create(anyString()).thenReturn(other);
when(other.concatenate(anyString()).thenReturn("expected");
ClassToTest created = mock.create("test");
String result = created.concatenate("lala");
assertThat(result).isEqualTo("expected"); // duh

Is it possible to mock the result of a private method and at the same time obtain coverage in sonar or jacoco?

I need to test a method which calls another private method, the problem is not to try to mock the result that the private method returns, but to do so not to obtain the coverage of jacoco or sonar. I tested with Powermock, with EasyMock but when using a spy, when use an spy the test is not covered by sonar or jacoco. The private method and the public method that make the call are at the same class.
Situation to test:
public class ClassOne {
private Object methodOne () {
.....
return object;
}
private Object mehodTwo () {
return Object name = mehtodOne ();
}
}
Test example:
package foo.bar;
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest(VlcPlayerMinimal.class)
public class VlcPlayerMinimalTest {
#Test
public void getVlcRcStatusTest() {
VlcPlayerMinimal vlcPlayerSpy = PowerMockito.spy(new VlcPlayerMinimal());
try {
PowerMockito.doReturn("{status: stopped, id: 2}").when(vlcPlayerSpy, "executeGetRequest", Mockito.any(), Mockito.any());
String vlcRcStatus = vlcPlayerSpy.getVlcRcStatus();
System.out.println(vlcRcStatus);
} catch (Exception e) {
e.printStackTrace();
fail("Unexpected exception thrown.");
}
}
}
No, it's not possible. Pick one or the other.
What would such "coverage" even prove? You are not actually covering it. Code coverage is a metric to help you identify spots that are not well tested, not one that you should try to trick into appearing higher than it really is.

Mockito - mock library call

I have the following structure
public class classAImpl implements classA {
public ClassC getTarget(Classc cObj) {
// library call
RegistryLib.init();
// some more code to construct cObj with more info
return cObj
}
}
// Registry Library Class
Class RegistryLibClass{
public void init() {
ClassD.builder.build();
}
}
My test class is trying to test a method which calls getTarget() method written above. I want to completely avoid executing getTarget() method which I am not been able even after mocking it. So far I have tried the following:
Class Testclass {
#Before
public void setUp() {
Testclass mock = PowerMockito.mock(Testclass.class);
PowerMockito.when(mock.getTarget(cObj)).thenReturn(cObj);
}
private ClassC getTarget(cObj) {
return cObj;
}
}
Any help is appreciated!
Assuming you want to test a method in Class B that calls getTarget from Class A, you would do this,
B b = new B();
A a = Mockito.mock(A.class);
C c = new C();
Mockito.when(a.getTarget(Mockito.any(C.class)).thenReturn(c);
boolean isPresent = b.someMethodToTest();
assertEquals("someMethodToTest was supposed to return true", true/*expected*/, isPresent);
Edit#1
You need to use Powermockito to mock the static method to return nothing as mentioned here
#PrepareForTest(RegistryLibClass.class) //at the top of the class
//inside your test
PowerMockito.mockStatic(RegistryLibClass.class);
Mockito.when(RegistryLibClass.init()).doNothing();
Disclaimer - I'm not that familiar with mockito, but wouldn't you normally mock the class you want to avoid using? Like this:
class Testclass {
#Before
public void setUp() {
//create some mock of expected cObj here to be returned.
classAImpl mock = PowerMockito.mock(classAImpl.class);
PowerMockito.when(
mock.getTarget(cObj.class /*Shouldn't this be class call?*/))
.thenReturn(cObj);
}
}
And then you would inject mock as dependency into the object that uses it and that you want to test.
If I'm wrong then feel free to ignore me, but thats how other mocking libraries I used worked. I'd advise you to go read some tutorials about mocking for tests regardless.
As side note, use of Class and class in names made this example extremely difficult to understand.
Your example is very confusing as you are trying to mock your test class itself instead of the main class.
Also you have mentioned that you are trying to test a method which calls getTarget() method, but I don't see any method in your class that calls getTarget() method.
I have put down a simple example below for your understanding. Let me know if this helps.
ClassA
public class ClassA {
public String method1() {
return "ClassA -> method1";
}
public static String method2() {
return "ClassA -> method2";
}
}
ClassB calls Class A methods
public class ClassB {
public void method1() {
System.out.println("ClassB -> method1");
new ClassA().method1();
ClassA.method2();
}
}
ClassB Test
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest(ClassA.class)
public class ClassBTest {
#Mock
ClassA mock;
#Before
public void setUp() throws Exception {
// Initialize mocks
MockitoAnnotations.initMocks(this);
// This is for mocking new objects
PowerMockito.whenNew(ClassA.class).withNoArguments().thenReturn(mock);
PowerMockito.when(mock.method1()).thenReturn("Mocked Method 1");
// This is for mocking static methods
PowerMockito.mockStatic(ClassA.class);
PowerMockito.when(ClassA.method2()).thenReturn("Mocked Method 2");
}
#Test
public void testMeth() {
System.out.println(new ClassA().method1()); // Prints - Mocked Method 1
System.out.println(ClassA.method2()); // Prints - Mocked Method 2
}
}

How to run PowerMock on dynamically created TestCase

I was trying to mock my test suites. My test framework creates test cases by scanning test files on disk. So each time the test cases are dynamically created.
I was trying to use PowerMock. Below is the thing I tried first.
public class GroupTestcase_T extends TestSuite {
static void run() {
scan();
junit.textui.TestRunner.run(g);
}
static void scan() {
// scan disk
for (MyTestCase t : tests) { addTest(t); }
}
}
#RunWith(PowerMockRunner.class)
#PrepareForTest(ClassToStub.class)
public class MyTestCase extends TestCase {
public MyTestCase(TestInfo info) {...}
#Override
protected void setUp() throws Exception {
PowerMockito.mockStatic(ClassToStub.class);
when(ClassToStub.methodToStub())
.thenReturn(new FakeProxy());
}
#Test
public void test() throws Exception {
// Test!
}
}
Above code seems not working:
Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
Those methods cannot be stubbed/verified.
2. inside when() you don't call method on mock but on some other object.
3. the parent of the mocked class is not public.
It is a limitation of the mock engine.
I traced the code and found that PowerMockRunner are not called at all.
Also I tried manually force Junit to run it with PowerMockRunner:
Result result = junit.run(new PowerMockRunner(MyTestCase.class));
PowerMockRunner has only one constructor that takes the test class as parameter. My test cases are different each time but all share the same class.
Any idea how to use PowerMock if TestCase are dynamically created?
I was using Junit 4 / PowerMock 1.5
You can generate your tests with the parameterized tests feature and apply the #PowerMockRule.
import static org.junit.Assert.assertTrue;
import java.util.Arrays;
import java.util.Collection;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.rule.PowerMockRule;
#RunWith(Parameterized.class)
#PrepareForTest(ClassToStub.class)
public class MyTestCase{
#Parameters
public static Collection<Object[]> scan() {
return Arrays.asList(new Object[][] {
{ new TestInfo() }, { new TestInfo() } });
}
#Rule
public PowerMockRule rule = new PowerMockRule();
public MyTestCase(TestInfo info) {
// ...
}
#Test
public void test() throws Exception {
PowerMockito.mockStatic(ClassToStub.class);
PowerMockito.when(ClassToStub.methodToStub()).thenReturn(new FakeProxy());
assertTrue(ClassToStub.methodToStub() instanceof FakeProxy);
}
}
Beware, in your example, you are mixing junit 3 (extends TestSuite, protected setUp) and junit 4 (#Test) test definitions.

mockito, spy- not sure how it's done for partial mocking

I have a class, where i want to mock certain methods of the class and test the others. That is the only way i can verity and assert that it's working.
class UnderTest{
public void methodToTest(){
methodToCall1()
methodToCall2()
}
public void methodToCall1(){
}
public void methodToCall2(){
}
}
Now, since i want to test the first method, i want to create a partial mock of UnderTest so i can verify that those two methods were called.
How do i achieve this in Mockito?
Thanks for your help!
You mentioned you wanted to do two things:
1. Create real partial mocks
2. Verify method invocations
However, since your goal is to validate that methodToCall1() and methodToCall2() were actually invoked, all you need to do is spy on the real object. This can be accomplished with the following code block:
//Spy UnderTest and call methodToTest()
UnderTest mUnderTest = new UnderTest();
UnderTest spyUnderTest = Spy(mUnderTest);
spyUnderTest.methodToTest();
//Verify methodToCall1() and methodToCall2() were invoked
verify(spyUnderTest).methodToCall1();
verify(spyUnderTest).methodToCall2();
If one of the methods are not called, for example methodToCall1, an Exception will be thrown:
Exception in thread "main" Wanted but not invoked:
undertest.methodToCall1();
...
package foo;
import static org.mockito.Mockito.verify;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Spy;
import org.mockito.runners.MockitoJUnitRunner;
#RunWith(MockitoJUnitRunner.class)
public class FooTest {
#Spy
private UnderTest underTest;
#Test
public void whenMethodToTestExecutedThenMethods1And2AreCalled() {
// Act
underTest.methodToTest();
// Assert
verify(underTest).methodToCall1();
verify(underTest).methodToCall2();
}
}

Categories