PowerMockito.verifyStatic method does not work - java

I am trying to use PowerMockito in order to test a static method in my service. I have the following test method:
#PrepareForTest(LoggingUtils.class)
#RunWith(PowerMockRunner.class)
public class SiteServiceImplTest {
#Test
public void test() {
// code omitted
PowerMockito.mockStatic(LoggingUtils.class);
Page<SiteDTO> result = siteService.findAll(request, sort);
PowerMockito.verifyStatic(LoggingUtils.class, Mockito.times(1));
}
}
But when I run this test, it throws the following error:
org.mockito.exceptions.misusing.NotAMockException:
Argument passed to verify() is of type Class and is not a mock!
Make sure you place the parenthesis correctly!
See the examples of correct verifications:
verify(mock).someMethod();
verify(mock, times(10)).someMethod();
verify(mock, atLeastOnce()).someMethod();
So, how can I use PowerMockito and test my static method?
The static method is as following:
LoggingUtils.info("The ...);

Verification of a static method is done in two steps:
First call PowerMockito.verifyStatic(Static.class) to start verifying behavior and then
Call the static method of the Static.class to verify.
For example:
PowerMockito.verifyStatic(Static.class); // 1
Static.firstStaticMethod(param); // 2
See documentation
Your test should look:
#RunWith(PowerMockRunner.class)
#PrepareForTest(LoggingUtils.class)
public class ServiceTest {
#Test
public void test() {
// mock all the static methods in a class called "LoggingUtils"
PowerMockito.mockStatic(LoggingUtils.class);
// execute your test
ServiceSite siteService = new ServiceSite();
siteService.find();
// Different from Mockito, always use PowerMockito.verifyStatic(Class) first
// to start verifying behavior
PowerMockito.verifyStatic(LoggingUtils.class, Mockito.times(1));
// IMPORTANT: Call the static method you want to verify
LoggingUtils.info(anyString());
}
}
public class ServiceSite {
SiteDTO find() {
LoggingUtils.info("123");
return new SiteDTO();
}
}

Related

Verify private static method on final class gets called using PowerMockito

I have the following class
public final class Foo {
private Foo() {}
public static void bar() {
if(baz("a", "b", new Object())) { }
}
private static boolean baz(Object... args) {
return true; // slightly abbreviated logic
}
}
And this is my Test:
#PrepareOnlyThisForTest(Foo.class)
#RunWith(PowerMockRunner.class)
public class FooTest {
#Test
public void bar() {
PowerMockito.mockStatic(Foo.class); // prepare
Foo.bar(); // execute
verifyPrivate(Foo.class, times(1)).invoke("baz", anyVararg()); // verify - fails
}
}
For that, I get the following error message - and I don't understand why...
Wanted but not invoked com.example.Foo.baz(
null );
However, there were other interactions with this mock.
Removing the prepare line above seems to make the verify line pass no matter for how many times you check for... :(
(Our SONAR code checks enforce that each test has some sort of assertXyz() in it (hence the call to verify()) and enforces a very high test coverage.)
Any ideas how to do this?
The problem with your code is that you mock Foo so your method implementations won't be called by default such that when you call Foo.call() it does nothing by default which means that it never avtually calls baz that is why you get this behavior. If you want to partially mock Foo, mock it using the option Mockito.CALLS_REAL_METHODS in order to make it call the real methods as you seem to expect, so the code should be:
#PrepareOnlyThisForTest(Foo.class)
#RunWith(PowerMockRunner.class)
public class FooTest {
#Test
public void bar() throws Exception {
PowerMockito.mockStatic(Foo.class, Mockito.CALLS_REAL_METHODS); // prepare
...
}
}

Use Mockito to Stub methods in the same class as the class under test (CUT)

I am trying to test some legacy code using Mockito, and the method is a of type void.
I have stubbed out a lot of the calls to methods in other classes, this works fine.
However, I also need to be able to stub out certain calls to other methods inside the same class.
Currently this is not working.
e.g. My Class is like below:
public class Test {
public Test(dummy dummy) {
}
public void checkTask(Task task, List <String> dependencyOnLastSuccessList) throws TaskException {
callToOtherClass.method1 // This works fine, I can stub it using mockito
updateAndReschedule(Long id, String message) // call to method in same class, I cannot stub it
}
public void updateAndReschedule(Long id, String message) {
//method logic.....
}
}
This is my testClass showing what I have at the minute:
#Test
public void testMyMethod() {
Test testRef = new Test(taskJob);
Test spy = spy (testRef);
// when a particular method is called, return a specific object
when(callToOtherClass.method1).thenReturn(ObjectABC);
//doNothing when my local method is called
doNothing().when(spy).updateAndReschedule(1, "test");
//make method call
spy.checkTask(ts, taskDependencies);
}
You should instantiante testRef as follows:
Test testRef = new Test(taskJob) {
public void updateAndReschedule(Long id, String message) {
//do nothing
}
};
No need for the spy.
In my opinion the spy object instead of mock.
Spy is a mock created as a proxy to an existing real object; some methods can be stubbed, while the unstubbed ones are forwarded to the covered object
The spy is more elegant than anonymous implementation of chosen methods
Look at the example:
Mockito: Trying to spy on method is calling the original method
the nice article about mockito You can read
http://refcardz.dzone.com/refcardz/mockito

Mocking static method that is called multiple times

I have a static method, that is used in multiple places, mostly in static initialization block. It takes a Class object as parameter, and returns the class's instance.
I want to mock this static method only when particular Class object is used as parameter. But when the method is called from other places, with different Class objects, it returns null.
How can we have the static method execute actual implementation in case of parameters other than the mocked one?
class ABC{
void someMethod(){
Node impl = ServiceFactory.getImpl(Node.class); //need to mock this call
impl.xyz();
}
}
class SomeOtherClass{
static Line impl = ServiceFactory.getImpl(Line.class); //the mock code below returns null here
}
class TestABC{
#Mocked ServiceFactory fact;
#Test
public void testSomeMethod(){
new NonStrictExpectations(){
ServiceFactory.getImpl(Node.class);
returns(new NodeImpl());
}
}
}
What you want is a form of "partial mocking", specifically dynamic partial mocking in the JMockit API:
#Test
public void testSomeMethod() {
new NonStrictExpectations(ServiceFactory.class) {{
ServiceFactory.getImpl(Node.class); result = new NodeImpl();
}};
// Call tested code...
}
Only the invocations that match a recorded expectation will get mocked. Others will execute the real implementation, when the dynamically mocked class is called.

Mock a constructor with parameter

I have a class as below:
public class A {
public A(String test) {
bla bla bla
}
public String check() {
bla bla bla
}
}
The logic in the constructor A(String test) and check() are the things I am trying to mock. I want any calls like: new A($$$any string$$$).check() returns a dummy string "test".
I tried:
A a = mock(A.class);
when(a.check()).thenReturn("test");
String test = a.check(); // to this point, everything works. test shows as "tests"
whenNew(A.class).withArguments(Matchers.anyString()).thenReturn(rk);
// also tried:
//whenNew(A.class).withParameterTypes(String.class).withArguments(Matchers.anyString()).thenReturn(rk);
new A("random string").check(); // this doesn't work
But it doesn't seem to be working. new A($$$any string$$$).check() is still going through the constructor logic instead of fetch the mocked object of A.
The code you posted works for me with the latest version of Mockito and Powermockito. Maybe you haven't prepared A?
Try this:
A.java
public class A {
private final String test;
public A(String test) {
this.test = test;
}
public String check() {
return "checked " + this.test;
}
}
MockA.java
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
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(A.class)
public class MockA {
#Test
public void test_not_mocked() throws Throwable {
assertThat(new A("random string").check(), equalTo("checked random string"));
}
#Test
public void test_mocked() throws Throwable {
A a = mock(A.class);
when(a.check()).thenReturn("test");
PowerMockito.whenNew(A.class).withArguments(Mockito.anyString()).thenReturn(a);
assertThat(new A("random string").check(), equalTo("test"));
}
}
Both tests should pass with mockito 1.9.0, powermockito 1.4.12 and junit 4.8.2
To my knowledge, you can't mock constructors with mockito, only methods. But according to the wiki on the Mockito google code page there is a way to mock the constructor behavior by creating a method in your class which return a new instance of that class. then you can mock out that method. Below is an excerpt directly from the Mockito wiki:
Pattern 1 - using one-line methods for object creation
To use pattern 1 (testing a class called MyClass), you would replace a call like
Foo foo = new Foo( a, b, c );
with
Foo foo = makeFoo( a, b, c );
and write a one-line method
Foo makeFoo( A a, B b, C c ) {
return new Foo( a, b, c );
}
It's important that you don't include any logic in the method; just the one line that creates the
object. The reason for this is that the method itself is never going
to be unit tested.
When you come to test the class, the object that you test will
actually be a Mockito spy, with this method overridden, to return a
mock. What you're testing is therefore not the class itself, but a
very slightly modified version of it.
Your test class might contain members like
#Mock private Foo mockFoo;
private MyClass toTest = spy(new MyClass());
Lastly, inside your test method you mock out the call to
makeFoo with a line like
doReturn( mockFoo )
.when( toTest )
.makeFoo( any( A.class ), any( B.class ), any( C.class ));
You can use matchers that are more specific than any() if you want to
check the arguments that are passed to the constructor.
If you're just wanting to return a mocked object of your class I think this should work for you. In any case you can read more about mocking object creation here:
http://code.google.com/p/mockito/wiki/MockingObjectCreation
With Mockito you can use withSettings(). For example if the CounterService required 2 dependencies, you can pass them as a mock:
UserService userService = Mockito.mock(UserService.class);
SearchService searchService = Mockito.mock(SearchService.class);
CounterService counterService = Mockito.mock(CounterService.class, withSettings().useConstructor(userService, searchService));
Starting with version 3.5.0 of Mockito and using the InlineMockMaker, you can now mock object constructions:
try (MockedConstruction mocked = mockConstruction(A.class)) {
A a = new A();
when(a.check()).thenReturn("bar");
}
Inside the try-with-resources construct all object constructions are returning a mock.
Without Using Powermock .... See the example below based on Ben Glasser answer since it took me some time to figure it out ..hope that saves some times ...
Original Class :
public class AClazz {
public void updateObject(CClazz cClazzObj) {
log.debug("Bundler set.");
cClazzObj.setBundler(new BClazz(cClazzObj, 10));
}
}
Modified Class :
#Slf4j
public class AClazz {
public void updateObject(CClazz cClazzObj) {
log.debug("Bundler set.");
cClazzObj.setBundler(getBObject(cClazzObj, 10));
}
protected BClazz getBObject(CClazz cClazzObj, int i) {
return new BClazz(cClazzObj, 10);
}
}
Test Class
public class AClazzTest {
#InjectMocks
#Spy
private AClazz aClazzObj;
#Mock
private CClazz cClazzObj;
#Mock
private BClazz bClassObj;
#Before
public void setUp() throws Exception {
Mockito.doReturn(bClassObj)
.when(aClazzObj)
.getBObject(Mockito.eq(cClazzObj), Mockito.anyInt());
}
#Test
public void testConfigStrategy() {
aClazzObj.updateObject(cClazzObj);
Mockito.verify(cClazzObj, Mockito.times(1)).setBundler(bClassObj);
}
}
Mockito has limitations testing final, static, and private methods.
Alternate Solution:
with jMockit testing library, you can do few stuff very easy and straight-forward as below:
Mock constructor of a java.io.File class:
new MockUp<File>(){
#Mock
public void $init(String pathname){
System.out.println(pathname);
// or do whatever you want
}
};
the public constructor name should be replaced with $init
arguments and exceptions thrown remains same
return type should be defined as void
Mock a static method:
remove static from the method mock signature
method signature remains same otherwise
Using Mockito 4 (but I suspect this is true for Mockito from 3.5.0 version) you can mock the constructor and, in the initializer, you can assert the values of the parameters.
For example:
try (MockedConstruction<A> constr = mockConstruction(A.class,
(mock, context) -> {
if (context.getCount() == 1) {
assertArrayEquals(context.arguments().toArray(), new Object[] {"test"});
} else {
fail("No more calls should happen");
}
})) {
// Do the rest of assertions.
}
Notice that you need to put the MockedConstruction instantiation in a try-with-resources otherwise the mocked construction is leaked outside the test.

How to tell a Mockito mock object to return something different the next time it is called?

So, I'm creating a mock object as a static variable on the class level like so... In one test, I want Foo.someMethod() to return a certain value, while in another test, I want it to return a different value. The problem I'm having is that it seems I need to rebuild the mocks to get this to work correctly. I'd like to avoid rebuilding the mocks, and just use the same objects in each test.
class TestClass {
private static Foo mockFoo;
#BeforeClass
public static void setUp() {
mockFoo = mock(Foo.class);
}
#Test
public void test1() {
when(mockFoo.someMethod()).thenReturn(0);
TestObject testObj = new TestObject(mockFoo);
testObj.bar(); // calls mockFoo.someMethod(), receiving 0 as the value
}
#Test
public void test2() {
when(mockFoo.someMethod()).thenReturn(1);
TestObject testObj = new TestObject(mockFoo);
testObj.bar(); // calls mockFoo.someMethod(), STILL receiving 0 as the value, instead of expected 1.
}
}
In the second test, I'm still receiving 0 as the value when testObj.bar() is called... What is the best way to resolve this? Note that I know I could use a different mock of Foo in each test, however, I have to chain multiple requests off of mockFoo, meaning I'd have to do the chaining in each test.
You could also Stub Consecutive Calls (#10 in 2.8.9 api). In this case, you would use multiple thenReturn calls or one thenReturn call with multiple parameters (varargs).
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.junit.Before;
import org.junit.Test;
public class TestClass {
private Foo mockFoo;
#Before
public void setup() {
setupFoo();
}
#Test
public void testFoo() {
TestObject testObj = new TestObject(mockFoo);
assertEquals(0, testObj.bar());
assertEquals(1, testObj.bar());
assertEquals(-1, testObj.bar());
assertEquals(-1, testObj.bar());
}
private void setupFoo() {
mockFoo = mock(Foo.class);
when(mockFoo.someMethod())
.thenReturn(0)
.thenReturn(1)
.thenReturn(-1); //any subsequent call will return -1
// Or a bit shorter with varargs:
when(mockFoo.someMethod())
.thenReturn(0, 1, -1); //any subsequent call will return -1
}
}
For all who search to return something and then for another call throw exception:
when(mockFoo.someMethod())
.thenReturn(obj1)
.thenReturn(obj2)
.thenThrow(new RuntimeException("Fail"));
or
when(mockFoo.someMethod())
.thenReturn(obj1, obj2)
.thenThrow(new RuntimeException("Fail"));
First of all don't make the mock static. Make it a private field. Just put your setUp class in the #Before not #BeforeClass. It might be run a bunch, but it's cheap.
Secondly, the way you have it right now is the correct way to get a mock to return something different depending on the test.
Or, even cleaner:
when(mockFoo.someMethod()).thenReturn(obj1, obj2);
For Anyone using spy() and the doReturn() instead of the when() method:
what you need to return different object on different calls is this:
doReturn(obj1).doReturn(obj2).when(this.spyFoo).someMethod();
.
For classic mocks:
when(this.mockFoo.someMethod()).thenReturn(obj1, obj2);
or with an exception being thrown:
when(mockFoo.someMethod())
.thenReturn(obj1)
.thenThrow(new IllegalArgumentException())
.thenReturn(obj2, obj3);

Categories

Resources