Mocking method calls of unknown instances in easymock - java

I have a class with a method like this
class MyClass(){
public String myMethod(){
Logger.info(new MyOtherClass().myOtherMethod());
}
}
How can I mock the call of myOtherMethod() with EasyMock?
Background :
Initially I wrote myOtherMethod as static method. For testing, as I cannot mock static method calls
I ended up writing an instance method which calls static method.I tried mocking the static method versin of my code with PowerMock, but it is showing some errors while working with JSR-303 bean validators (please see here) and also I didn't find any working solution for integrating PowerMockRunner with SpringJunit4ClassRunner which is one of my case.

You can use PowerMock.expectNew(...) mocking functionality as described here.
Make sure you have annotated the test case class correctly. Many times folks miss out on the detail that you have to use the class invoking the constructor in the #PrepareForTest(ClassThatCreatesTheNewInstance.class) annotation.
If you still face error, please post your Test case code and stack trace.

Related

How to mock private enum using Powermock?

I have following class:
public class MyClazz
{
private static enum MyEnum
{
INSTANCE;
private MyClazzB getMyClazzB()
{
....
return
}
final MyClazzB b = getMyClazzB();
}
public void methodWhichIWantTest(arguments)
{
//...
//here is logic which I want to test
//...
MyEnum.INSTANCE.b.doSomething();//I want to mock this line.
}
}
I am not author of MyClazz and I do not want to change anything. I only want to test methodWhichIWantTest method. The problem is that method getMyClazzB throws exception. I do not how to mock it.
How to mock it? I think that I should mock MyEnum class but it is private.
===EDIT===
I think that I should clarify my question because I got some comments.
I am not author of MyClazz but this class is part of my project and I can edit this class but I would like to avoid editing as much as possible. I fixed some bug in private method of MyClazz. I would like to write some test which tests my fix. Testing private method is not good practice so I can write integration test or write unit test for some public method which calls this private method. Firstly I wanted to write integration test but after research I found that integration test is to complicated and takes me too much time. So I decided to write unit test for some public method which calls this private method. methodWhichIWantTest is this public method. Method getMyClazzB throws exception because it crates javax.naming.InitialContext and lookup some beans (It works properly on wildfly but it does not work inside simple unit test).
I think that I have following options:
do not test it
write integration test (it is time consuming)
try to mock MyEnum and write unit test
try to mock InitialContext and write unit test
edit source code, mock and write unit test.
test private method directly using java reflection
My question is related to point 3. I do not know how to realize point 3 I was curious how to do it so I asked my question.
I am afraid that realizing point 3 is not possible within a reasonable time.
Thank you for help.
how-to-mock-an-enum-singleton-class-using-mockito-powermock does not solve my issue because MyEnum enum is a private. E.g. I cannot use #PrepareForTest({MyEnum.class}) annotation because MyEnum is not accessible.

PowerMockito returns null when mock constrtuctor is defined for any arguments

I've been trying to figure out what's the deal with PowerMockito's constructor mocking. My code is similar to the following:
public void testConstruction() {
whenNew(Account.class).withAnyArguments().thenReturn(mock(Account.class));
assertNotNull(new Account("name")); //fails
}
I'm not really sure where else to look for to find what's causing this issue. With the above stubbing code, PowerMockito will only return the object created by mock(Account.class) when I call the constructor with no arguments; it's acting as if I stubbed it using withNoArguments(). I'm sure that my test class is set up correctly because the following code passes:
public void testConstruction() {
whenNew(Account.class).withArguments("name").thenReturn(mock(Account.class));
assertNotNull(new Account("name")); //passes
}
I ran into similar issue. withAnyArguments doesn't behave as expected if the class being mocked has more than one constructor. In my case the class mocked with whenNew had 2 constructors and I would always get null when new instance of this class was created. https://github.com/powermock/powermock/issues/891 gave some hint and I switched to using withArguments.

Why does PowerMock try to load some classes, which are used in non-mocking class method?

I use JUnit4 with Mockito for Unit Testing, and now I'm trying to add PowerMock into my toolbox.
And at once I'm facing a weird class loading behaviour of PowerMock. So, I use some code like that:
#PrepareForTest(ClassToMock.class)
public class MyTest
{
#Rule
public PowerMockRule rule = new PowerMockRule();
#Test
public void myTest() throws Exception
{
// some test code using ClassToMock
MyHelper.staticMethod(param);
// some other test code
}
}
MyHelper is some class from another bundle, and staticMethod() is some method, which I don't need to be mocked. This method uses Google Gson and some my serializers (let's say - MySerializer class).
And PowerMock throws me a javassist.NotFoundException for Google Gson and MySerializer.
For example:
Caused by: javassist.NotFoundException: com.google.gson.GsonBuilder
at javassist.ClassPool.get(ClassPool.java:450)
at org.powermock.core.classloader.MockClassLoader.loadUnmockedClass(MockClassLoader.java:220)
I can add those classes to the classpath (to the Impored-Packages), but I don't want to. And why does PowerMock try to load classes, which are used inside some method, which supposed to be just a "black box", at the first place?
Can anyone explain that, please?
Also, I can get rid of loading Gson using #PowerMockIgnore("com.google.*") annotation, but it doesn't work for MySerializer. And it doesn't seem like a proper solution anyway.
Thanks!
your classes might be using
static blocks
which needs to be suppressed using powermock, so that it does not go and load all the required classes by those static blocks
refer this link to see the usage of SuppressUnwantedBehavior

Mockito: Trying to spy on method is calling the original method

I'm using Mockito 1.9.0. I want mock the behaviour for a single method of a class in a JUnit test, so I have
final MyClass myClassSpy = Mockito.spy(myInstance);
Mockito.when(myClassSpy.method1()).thenReturn(myResults);
The problem is, in the second line, myClassSpy.method1() is actually getting called, resulting in an exception. The only reason I'm using mocks is so that later, whenever myClassSpy.method1() is called, the real method won't be called and the myResults object will be returned.
MyClass is an interface and myInstance is an implementation of that, if that matters.
What do I need to do to correct this spying behaviour?
Let me quote the official documentation:
Important gotcha on spying real objects!
Sometimes it's impossible to use when(Object) for stubbing spies. Example:
List list = new LinkedList();
List spy = spy(list);
// Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)
when(spy.get(0)).thenReturn("foo");
// You have to use doReturn() for stubbing
doReturn("foo").when(spy).get(0);
In your case it goes something like:
doReturn(resultsIWant).when(myClassSpy).method1();
In my case, using Mockito 2.0, I had to change all the any() parameters to nullable() in order to stub the real call.
My case was different from the accepted answer. I was trying to mock a package-private method for an instance that did not live in that package
package common;
public class Animal {
void packageProtected();
}
package instances;
class Dog extends Animal { }
and the test classes
package common;
public abstract class AnimalTest<T extends Animal> {
#Before
setup(){
doNothing().when(getInstance()).packageProtected();
}
abstract T getInstance();
}
package instances;
class DogTest extends AnimalTest<Dog> {
Dog getInstance(){
return spy(new Dog());
}
#Test
public void myTest(){}
}
The compilation is correct, but when it tries to setup the test, it invokes the real method instead.
Declaring the method protected or public fixes the issue, tho it's not a clean solution.
The answer by Tomasz Nurkiewicz appears not to tell the whole story!
NB Mockito version: 1.10.19.
I am very much a Mockito newb, so can't explain the following behaviour: if there's an expert out there who can improve this answer, please feel free.
The method in question here, getContentStringValue, is NOT final and NOT static.
This line does call the original method getContentStringValue:
doReturn( "dummy" ).when( im ).getContentStringValue( anyInt(), isA( ScoreDoc.class ));
This line does not call the original method getContentStringValue:
doReturn( "dummy" ).when( im ).getContentStringValue( anyInt(), any( ScoreDoc.class ));
For reasons which I can't answer, using isA() causes the intended (?) "do not call method" behaviour of doReturn to fail.
Let's look at the method signatures involved here: they are both static methods of Matchers. Both are said by the Javadoc to return null, which is a little difficult to get your head around in itself. Presumably the Class object passed as the parameter is examined but the result either never calculated or discarded. Given that null can stand for any class and that you are hoping for the mocked method not to be called, couldn't the signatures of isA( ... ) and any( ... ) just return null rather than a generic parameter* <T>?
Anyway:
public static <T> T isA(java.lang.Class<T> clazz)
public static <T> T any(java.lang.Class<T> clazz)
The API documentation does not give any clue about this. It also seems to say the need for such "do not call method" behaviour is "very rare". Personally I use this technique all the time: typically I find that mocking involves a few lines which "set the scene" ... followed by calling a method which then "plays out" the scene in the mock context which you have staged... and while you are setting up the scenery and the props the last thing you want is for the actors to enter stage left and start acting their hearts out...
But this is way beyond my pay grade... I invite explanations from any passing Mockito high priests...
* is "generic parameter" the right term?
One more possible scenario which may causing issues with spies is when you're testing spring beans (with spring test framework) or some other framework that is proxing your objects during test.
Example
#Autowired
private MonitoringDocumentsRepository repository
void test(){
repository = Mockito.spy(repository)
Mockito.doReturn(docs1, docs2)
.when(repository).findMonitoringDocuments(Mockito.nullable(MonitoringDocumentSearchRequest.class));
}
In above code both Spring and Mockito will try to proxy your MonitoringDocumentsRepository object, but Spring will be first, which will cause real call of findMonitoringDocuments method. If we debug our code just after putting a spy on repository object it will look like this inside debugger:
repository = MonitoringDocumentsRepository$$EnhancerBySpringCGLIB$$MockitoMock$
#SpyBean to the rescue
If instead #Autowired annotation we use #SpyBean annotation, we will solve above problem, the SpyBean annotation will also inject repository object but it will be firstly proxied by Mockito and will look like this inside debugger
repository = MonitoringDocumentsRepository$$MockitoMock$$EnhancerBySpringCGLIB$
and here is the code:
#SpyBean
private MonitoringDocumentsRepository repository
void test(){
Mockito.doReturn(docs1, docs2)
.when(repository).findMonitoringDocuments(Mockito.nullable(MonitoringDocumentSearchRequest.class));
}
Important gotcha on spying real objects
When stubbing a method using spies , please use doReturn() family of methods.
when(Object) would result in calling the actual method that can throw exceptions.
List spy = spy(new LinkedList());
//Incorrect , spy.get() will throw IndexOutOfBoundsException
when(spy.get(0)).thenReturn("foo");
//You have to use doReturn() for stubbing
doReturn("foo").when(spy).get(0);
I've found yet another reason for spy to call the original method.
Someone had the idea to mock a final class, and found about MockMaker:
As this works differently to our current mechanism and this one has different limitations and as we want to gather experience and user feedback, this feature had to be explicitly activated to be available ; it can be done via the mockito extension mechanism by creating the file src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker containing a single line: mock-maker-inline
Source: https://github.com/mockito/mockito/wiki/What%27s-new-in-Mockito-2#mock-the-unmockable-opt-in-mocking-of-final-classesmethods
After I merged and brought that file to my machine, my tests failed.
I just had to remove the line (or the file), and spy() worked.
One way to make sure a method from a class is not called is to override the method with a dummy.
WebFormCreatorActivity activity = spy(new WebFormCreatorActivity(clientFactory) {//spy(new WebFormCreatorActivity(clientFactory));
#Override
public void select(TreeItem i) {
log.debug("SELECT");
};
});
As mentioned in some of the comments, my method was "static" (though being called on by an instance of the class)
public class A {
static void myMethod() {...}
}
A instance = spy(new A());
verify(instance).myMethod(); // still calls the original method because it's static
Work around was make an instance method or upgrade Mockito to a newer version with some config: https://stackoverflow.com/a/62860455/32453
Bit late to the party but above solutions did not work for me , so sharing my 0.02$
Mokcito version: 1.10.19
MyClass.java
private int handleAction(List<String> argList, String action)
Test.java
MyClass spy = PowerMockito.spy(new MyClass());
Following did NOT work for me (actual method was being called):
1.
doReturn(0).when(spy , "handleAction", ListUtils.EMPTY_LIST, new String());
2.
doReturn(0).when(spy , "handleAction", any(), anyString());
3.
doReturn(0).when(spy , "handleAction", null, null);
Following WORKED:
doReturn(0).when(spy , "handleAction", any(List.class), anyString());

Mockito Exception - when() requires an argument which has to be a method call on a mock

I have a very simple test case that is using Mockito and Spring Test framework. When I do
when(pcUserService.read("1")).thenReturn(pcUser);
I get this exception.
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.
2. inside when() you don't call method on mock but on some other object.
at com.project.cleaner.controller.test.PcUserControllerTest.shouldGetPcUser(PcUserControllerTest.java:93)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
I have tried with different methods but keep on getting this error message. I am using Spring 3.1.0.RELEASE with Mockito. Please share and guide me in the right direction.
You need to create a MOCK of pcUserService first, and then use that mock.
PcUserService mock = org.mockito.Mockito.mock(PcUserService.class);
when(mock.read("1")).thenReturn(pcUser);
In case others hit this issue....
It could also be the case that the method you are trying to mock out,pcUserService.read, is declared as a final method. From what I've noticed this appears to cause issues with Mockito.
If you use Kotlin, you should know that methods are final by default. So write open fun instead of fun. Thanks to #djkelly99 for a tip.
Another solution to this issue might be that in case of a test class that is using PowerMockRunner, you might have to add the class that you are mocking to the list, in #PrepareForTest annotation.
For instance -
#PrepareForTest({ PcUserService.class })
In my case it was solved by injecting #MockBean.
For ex.
#MockBean
StateRepository mockStateRepository;
There's another possible reason for such error - sometimes IDE prefers to statically import Mockito.when() from another package:
import static io.codearte.catchexception.shade.mockito.Mockito.when;
vs
import static org.mockito.Mockito.when; //should normally use this one
The thing is 'when' from io.codearte package is compliant with org.mockito.Mockito.any() on compilation level, but fails during runtime with that exact same error message.
I had the same issue, the method that I was trying to mock it was a final method. I removed the modifier and it worked fine.
For the help of others who stuck with the same problem;
The method you are trying to mock , pcUserService.read, is declared as a final method. Static methods appears to cause issues with Mockito.
If you get this exception when using MockedStatic or Mockito.mockStatic, it can also mean that you are mixing matchers and literals in the call to the static method.
Try changing any mixes like YourClass.staticMethod(any(), "literal") to YourClass.staticMethod(any(), eq("literal"))
Basically You need to use the PowerMockito.mockStatic to enable static mocking for all static methods of a class. This means make it possible to stub them using the when-thenReturn syntax.
For example:
PowerMockito.mockStatic(TestClass.class);
when(TestClass.getString()).thenReturn("HelloWorld!");
Note: you have to add #PrepareForTest({ TestClass.class }) to your unit test class.
If you use KOIN, include in the gradle's dependencies:
dependencies {
...
testImplementation "org.koin:koin-test:2.0.0"
}
I faced similar issue when mocking static method of anotherClass called inside testing a method of someClass. In that case, we need to add #PrepareForTest({anotherClass.class, someClass.class}) both the class having the static method and caller class.
When I got this exception, I was using #InjectMocks on the class that I needed to have the #Mock objects injected into (via constructor injection).
AFter much searching, I finally stumbled across this article:
https://mkyong.com/spring-boot/mockito-when-requires-an-argument-which-has-to-be-a-method-call-on-a-mock/
The key part to take away from it is (from the article):
When Mockito see this #InjectMocks, it doesn’t mock it, it just
creates a normal instance, so the when() will be failed.
So this make this exception message I was getting
when() requires an argument which has to be 'a method call on a mock'.
make sense now; you aren't using when on an actual mock but an actual instance.
The link also provides the solution to the problem:
To solve it, annotate #Spy to mock it partially.
On top of #InjectMocks, put #Spy.
As a side note, if you try to make it a Mock by putting #Mock on top of #InjectMocks, you will get exception:
org.mockito.exceptions.base.MockitoException: This combination of
annotations is not permitted on a single field: #Mock and #InjectMocks
Using #Spy on top of #InjectMocks solved the problem for me.
I faced same issue and it was because the mocked object is defined as #Beanand the overriden #Bean in the test was not working because of a missing spring property value
#Bean
#Primary
public JwtTokenUtil jwtTokenUtil() {
return Mockito.mock(JwtTokenUtil.class);
}
#Autowired
private JwtTokenUtil jwtTokenUtil;
when(jwtTokenUtil.validateToken(jwtToken)).thenReturn(true);
Fix
spring.main.allow-bean-definition-overriding=true in application-test.properties
if anything above answers your case, then check that you did missed the #Test annotation for your test method.
#Test
public void my_test_method(){
}
just quoting, as this was my case. just missed the annotation.

Categories

Resources