Mocking a static method with a generic parameter - java

I have the following setup :
Class to test : SeriesOffset which extends BaseDisplayOption
Test Class : SeriesOffsetTest
When creating an object of the SeriesOffset class to test it, the constructor of the same makes a super call which then makes the following method call :
logger = LoggingService.getLog(this.getClass());
where LoggingService is an abstract class and getLog(Class<?> clazz) is a static method with a generic class parameter. This very method call needs to be mocked. I created a mock implementation for the same with a class called ILogImpl and this is how I am trying to test it:
ILogImpl a = new ILogImpl();
PowerMockito.mockStatic(LoggingService.class);
PowerMockito.when(LoggingService.getLog( SeriesOffset.class)).thenReturn(a);
But this method doesnt seem to work and it calls the real implementation instead of the mock one that I need it to call.
The error trace is the following : error trace

According to the error trace, I don't see where your real implementation of getLog is being called—but the real class initializer ("clinit") is being called as part of mock creation, because you're at least referring to the actual class and its static fields and static {} blocks are being loaded as usual.
Look to line 41 of LoggingService.java, and if the problem isn't obvious there, edit your answer so we can see it and diagnose further.

Related

haven't provide instance field declaration so I tried to construct the instance.However the constructor or the initialization block threw an exception

class Example extends Parent{
public Example() {
super(Example.class)
}
whenever I am trying the
public class Test{
#InjectMock Example example
#BeforeMethod
#BeforeTest
public void setUp(){
MockitoAnnotations.initMocks(this)
}
}
It is giving the above error mentioned.
Any help is appreciated.
there are a pair of things in your code which not used correctly. I think there is a bit of confusion and is not clear enough what you what to do. I'll try to explain e give you something to read.
#Injectmocks annotation in Test class
The #Injectmocks annotation is used to create a real instance of a class in which you want to inject #Mock objects.
Take a look here for some examples:
https://howtodoinjava.com/mockito/mockito-mock-injectmocks/ ,
https://www.baeldung.com/mockito-annotations
The annotation is an instance field annotation. This means that you cannot use that as you are doing on a method declaration, but you need to use that instead on a field into the test class.
Let's suppose you want to test a method in a class, then you will use this annotation to create an instance of that class which contains the method to be tested. Roughly speaking with analogies, injectmock is like the Spring #Autowire annotation, although not the same.
I've noticed now that probably this is what you where trying to do (the puplished code of the test class has not been highlighetd correctly). You should put new line after #InjectMock Example example. In any case, I think there is a mistake in how you use the super keyword.
Call to super constructor in Example constructor.
I don't know what is the constructor in Parent class and how is done, but the rule is you pass arguments of the Parent construtor in super keyword. So for exampe, if this is your parent constructor:
public Parent(String name){
this.name = name}
then you need to do this in Example:
public Example(String name, String code) {
this.code = code;
super(name);
}
You are passing a .class in super(), not a field.
I would like to give you more help. I suggest you to post your code more clearly and with complete classes.

Mockito - mock subclass method call

I am working with legacy code and trying to write a unit test for an implementation I did. I have the following structure:
AbstractClass:
----------------
public AbstractClass {
abstract method2();
void method1(){
...does something...
..calls --> method2()
}
}
Subclass
------------
public Subclass extends AbstractClass(){
void method2(){
..do something....
..mockThisMethod()...
return true;
}
}
I have an abstract class which has some logic implemented in a specific method.
This method calls than another method implemented in the subclass. The method in the subclass calls other methods which I want to mock.
Is this possible without changing the implementation code (hard to change)?
Mos of the results are suggesting using mockito spying but it doesn't work.
I followed the TestDesign describer here:
https://www.tildedave.com/2011/03/06/pattern-stubbing-legacy-superclasses-with-mockito-spies.html
What I did is:
Subclass subclass= spy(Subclass.class);
when(subclass.mockThisMethod()).thenReturn(something);
subclass.method1() (I am not sure if this line is correct?)
So what I want to avoid is, calling the method (mockThisMethod) in the Subclass.
Since this method does some db-stuff an so on. I know it would be easier to test, if I use object composition instead of inheritance but at this point, it is hard to change the whole implementation. The code above is not working..I get a NPE.
1) You do not create a Spy by passing the class to the static Mockito.spy method.
Instead, you must pass an instance of that particular class:
Subclass subclassSpy = spy(new Subclass());
Also, consider using annotations:
#Spy
private Subclass subclassSpy = new Sublcass();
#Before
public void init(){
MockitoAnnotations.initMocks(this);
}
2) Avoid using when.thenReturn when stubbing a spy.
Instead, use doReturn..when..methodCall:
doReturn(something).when(sublcass).mockThisMethod();
otherwise you will invoke the actual method while stubbing and this may lead to unwanted behavior and/or exceptions.

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.

Mocking method calls of unknown instances in easymock

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.

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());

Categories

Resources