PowerMockito doesn't mock the new instance called in the tested class - java

I have the following class where, in the constructor, I call another constructor to build a field of the class:
public class ClassIWantToTest {
private ClassIWantToMock anotherClass;
public ClassIWantToTest() {
//some stuff
anotherClass = new ClassIWantToMock(); //<-- call constructor to build the field
//some other stuff
}
}
When I test the class ClassIWantToTest, I want to mock the instance of ClassIWantToMock.
Hence, I've set up my test as follows:
#RunWith(PowerMockRunner.class)
#PrepareForTest(ClassIWantToMock.class)
public class ClassIWantToTest_Test {
#Test
public void myFirstTest() {
ClassIWantToMock myMock = PowerMockito.mock(ClassIWantToMock.class);
PowerMockito.whenNew(ClassIWantToMock.class).withAnyArguments().thenReturn(myMock);
ClassIWantToTest test = new ClassIWantToTest(); //<-- not mocked
}
}
However, in the last line of code in the test (where I make a new of the class I want to test), the constructor of ClassIWantToMock is still called.
I've searched other examples on Stack Overflow (and in documentation), but it seems that it should be done like this. What am I forgetting/doing wrong?

It was indeed a simple mistake. If the class ClassIWantToMock is initialized inside ClassIWantToTest, then also ClassIWantToTest should be prepared for test.
I replaced this:
#PrepareForTest(ClassIWantToMock.class)
with this:
#PrepareForTest({ClassIWantToTest.class,ClassIWantToMock.class})
... and it worked fine.

Related

Powermock verifyPrivate does not work with any()

I have a private method whose invocation I want to test without caring about the arguments. I want to test if it was called at all or not.
MyClass.java
public void doStuff(){
unload(args);
}
private void unload(List<String> args) {
//
}
So I used following:
MyClasstest.java
MyClass myClass = PowerMockito.spy(new MyClass());
myClass.doStuff();
verifyPrivate(myClass, times(1)).invoke("unload",any(List.class));
// verifyPrivate(myClass, times(1)).invoke("unload",any()); //same result with this
This test fails with following exception:
Wanted but not invoked com.MyClass.unload(
null );
However, there were other interactions with this mock .......
(actual values with which it was called)
Can verifyPrivate be called with only actual arguments & not with any()?
Here is a working example of what you are trying to do:
You might just missing the #PrepareForTest annotation, which has to point to the correct class. If your class is an external one use #PrepareForTest(MyClass.class), the example below shows it with an internal class.
#RunWith(PowerMockRunner.class)
#PrepareForTest(MyClassTest.class)
public class MyClassTest {
static class MyClass {
public void doStuff(){
unload(null);
}
private void unload(List<String> args) {
}
}
#Test
public void test() throws Exception {
MyClass myClass = PowerMockito.spy(new MyClass());
myClass.doStuff();
PowerMockito.verifyPrivate(myClass, Mockito.times(1)).invoke("unload", Mockito.any());
}
}
Note that you should consider whether you really want to do this in a UnitTest. Normally your UnitTest should not be concerned about whether a private method is used or not, it should be focused on verifying that the correct result is returned or the correct object state is reached.
By adding knowledge about the internal behaviour of the class into it, you test is tightly coupled to the implementation which might not be a good thing.

Powermock not intercepting new object creation

I am attempting to test a method that creates a new instance of another class that I wish to mock using powermock. My code (simplified) is as follows -
Testing code:
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.easymock.EasyMock.anyObject;
import static org.powermock.api.easymock.PowerMock.*;
#RunWith(PowerMockRunner.class)
#PrepareForTest( { ClassUnderTest.class } )
public class TestForClassUnderTest {
private ClassToBeMocked classToBeMocked;
private ClassUnderTest classUnderTest;
public void testSimple() throws Exception {
classToBeMocked = createMock(ClassToBeMocked.class);
// trying to intercept the constructor
// I *think* this is the root cause of the issue
expectNew(ClassToBeMocked.class, anyObject(), anyObject(), anyObject()).andReturn(classToBeMocked);
classToBeMocked.close();
expectLastCall();
replayAll();
// call to perform the test
classUnderTest.doStuff();
}
}
Code that is being tested:
import ClassToBeMocked;
public class ClassUnderTest {
private ClassToBeMocked classToBeMocked;
public void doStuff() {
classToBeMocked = new ClassToBeMocked("A","B","C");
// doing lots of other things here that I feel are irrelevant
classToBeMocked.close();
}
}
Code that I wish to mock:
public class ClassToBeMocked {
public ClassToBeMocked(String A, String B, String C) {
// irrelevant
}
public close() {
// irrelevant
}
}
The error I get is as below:
java.lang.ExceptionInInitializerError
at ....more inner details of where this goes into
at ClassToBeMocked.close
at ClassUnderTest.doStuff
at TestForClassUnderTest.test.unit.testSimple
Caused by: java.lang.NullPointerException
PowerMock version:1.4.5
EasyMock version: 3.1
PS: I have stripped down the code to bare minimums, only showing the details of the mocking library, let me know if you think my other code is somehow interfering and I can give more details on the bits you think are important to show. Any links to other examples doing this may even help.
I realized that the reason this wasn't working was because I was extending another class. I had
#RunWith(PowerMockRunner.class)
#PrepareForTest( { ClassUnderTest.class } )
public class TestForClassUnderTest extends AnotherClass {
}
as soon as I removed the extends, it worked. Not sure if its just not able to extend another class with powermock or due to AnotherClass, but removing it worked for me
whenever you wish to mock a new instance of any class, you should be doing like this
Powermock.expectNew(ClassYouWishToMock.class).andReturn(whateverYouWantToReturn).anyTimes();
Powermock.replayAll();
this will return 'whateverYouWantToReturn' whener new is called on this class.
but whenever you want to mock a instance variable, you should be using Whitebox feature of easymock.
have a look at following Example
Class A{
private B b;
}
to mock this my test class will look something like this
...//other powermock, easymock class level annotations
#PrepareForTest(B.class)
class ATest{
Whitebox.setInternalState(B.class,b,whateverValueYouWantYourMockedObjectToReflect);
}
here 'b' passed in parameter, is the variable name you want to mock.
Good Luck!

How do you mock classes that are used in a service that you're trying to unit test using JUnit + Mockito

I want to write a unit test for a service that uses/depends on another class. What i'd like to do is mock the behavior of the dependent class (As opposed to an instance of that class). The service method being tested uses the dependent class internally (i.e. an instance of the dependent class isn't passed in to the method call) So for example I have a service method that I want to test:
import DependentClass;
public class Service {
public void method() {
DependentClass object = new DependentClass();
object.someMethod();
}
}
And in my unit test of Service method(), I want to mock someMethod() on the DependentClass instance instead of having it use the real one. How do I go about setting that up in the unit test?
All of the examples and tutorials i've seen show mocking object instances that are passed in to the method being tested, but I haven't seen anything showing how to mock a class as opposed to an object instance.
Is that possible with Mockito (Surely it is)?
It's easy with Powermockito framework and whenNew(...) method. Example for your test as follows:
#Test
public void testMethod() throws Exception {
DependentClass dependentClass = PowerMockito.mock(DependentClass.class);
PowerMockito.whenNew(DependentClass.class).withNoArguments().thenReturn(dependentClass);
Service service = new Service();
service.method();
}
Hope it helps
This is a problem of poor design. You can always take in the param from a package private constructor.
Your code should be doing something like this:
public class Service {
DependentClass object;
public Service(){
this.object = new DependentClass();
}
Service(DependentClass object){ // use your mock implentation here. Note this is package private only.
object = object;
}
public void method() {
object.someMethod();
}
}

How to test a static method without running a piece of code in it

A piece of code is like this:
public class ClassToTest {
public static A method1(arguments here){
//a log of code here
A a = new A();
return a;
}
}
The problem is the constructor call new A() is in a library and I don't want method1 to call this constructor in my test because it is not necessary for my current test and it contains some network connections. I want my unit test get rid of any external dependencies.
Generally in a unit test, we don't want to do any modification to the source code. But in order to test the critical logic in method1, It is acceptable to make some reasonable change to the source code.
At first I think I could move the new A() to another method and build a subclass and then override that method. This change is also reasonable without considering testing so I think it is acceptable. But adding a flag for test only is not acceptable.
But I cannot do this because the method I need to test is static.
Is there any other way to test this piece of code without running the line A a = new A()?
If you don't want that method to introduce state, then use PowerMockito.mockStatic() to mock the return value. This makes the assumption that your static method has no side effects, and if it doesn't, you really should write it so that it doesn't.
#RunWith(PowerMockRunner.class)
public class ClassToTestTest {
private ClassToTest classMock;
private ClassToTest testObject;
#Before
public void init() {
testObject = new ClassToTest();
}
#Test
public void example() {
Object args = new Object();
PowerMockito.mockStatic(ClassToTest.class);
doReturn(new A()).when(ClassToTest.class, "method1", args);
}
}
doReturn will allow you to set up what it's going to ultimately give back after execution of your static method.

Mockito/PowerMockito mocking private factory method

I want to use pattern 1 suggested in the following link:
https://code.google.com/p/mockito/wiki/MockingObjectCreation
and have the following class:
public class MyClass {
private AnyType anyObject;
private Foo foo; // Foo is a thirdparty class
public MyClass(AnyType anyObject) {
//...
foo = makeFoo();
}
private Foo makeFoo() {
return new Foo();
}
}
I'm trying to make a test as follows:
#Test
public void myTestMethod() {
MyClass myClass = Mockito.spy(new MyClass());
// now i want to do something like this:
Foo mockFoo= Mockito.mock(Foo.class);
// Mockito.doReturn(mockFoo).when(myClass).makeFoo());
}
The problem is my factory method makeFoo is a private method, so I can't access it. I don't want to make it public just for the test. My test classes are not in the same package as my productive code either, so making it visible only for the package won't work.
Update:
Now i found another problem. Assumed that makeFoo() is public, 'mockFoo' will not be returned either, yet the real makeFoo() method is invoked. This happens since the invocation of makeFoo() (in the constructor of MyClass) is prior to the creation of mockFoo.
Does anyone know how to solve this problem or am I doing something totally wrongly?
Thanks you guys in advance for helping!!
Have a look at whenNew of PowerMockito. This allows to "overwrite" the constructor call of an object and return a mock of it instead.
http://powermock.googlecode.com/svn/docs/powermock-1.3.7/apidocs/org/powermock/api/mockito/PowerMockito.html#whenNew%28java.lang.Class%29
http://www.gitshah.com/2010/05/how-to-mock-constructors-using.html
If you just need to set a field inside your class, it's doable with MockitoAnnotations
You just need to create fields you need, annotate them and in unit test before section call MockitoAnnotations.initMocks(this)
In your case it will look like:
#Spy
#InjectMocks
MyClass myClass;
#Mock
Foo foo;
#Before
public void initMocks() {
MockitoAnnotations.initMocks(this);
}
Please read also documentation above.

Categories