I want to mock static method which is called within other static method.
public class MyClass
{
public static void methodA(String s)
{
...
methodB(s);
...
}
public static void methodB(String s)
{
...
}
}
So, I want to mock methodA, but I want to skip calling methodB.
I tried almost all solutions that I was able to find, without any success. Every time methodB is called.
Some solutions that I used:
PowerMockito.suppress(method(MyClass.class, "methodB"));
MyClass.methodA("s");
_
PowerMockito.stub(method(MyClass.class, "methodB"));
MyClass.methodA("s");
_
PowerMockito.mockStatic(MyClass.class);
doNothing().when(MyClass.class, "methodB", anyString());
MyClass.methodA("s");
And many others...
Anyone have an idea how to solve this problem?
In my opinion you should Spy your class instead of mocking it.
In that situation all the static methods will be called with real implementation and on top of that you could instruct to not call methodB:
#RunWith(PowerMockRunner.class)
#PrepareForTest(MyClass.class)
class MyClassTest
{
#Test
public void test()
{
PowerMockito.spy(MyClass.class);
doNothing().when(MyClass.class, "methodB", anyString());
MyClass.methodA("s");
}
}
I have written an article on Mocking Static Methods if you need a further read.
Related
I'm trying to test a method that calls an external util static method for a check, and need to somehow mock it to return true / false conditions, here is a sample:
class foo {
public void methodToTest(){
..logic
boolean myCondition = SomeUtil.checkCondition(args);
..more logic
}
}
Is this possible to do with mockito only? If not directly, is there a way to replace the SameUtil method with reflection or something similar?
I saw people suggesting powermock, but they don't have mockito 3.x listed on their compatibility chart, is there a better option?
This seems like a pretty common case, not everything should be autowired or injected.
Option 1: factor out the static method call into a separate method and use Mockito spy:
class Foo {
public void methodToTest(){
checkCondition(args);
// ....
}
boolean checkCondition(Object args) {
return SomeUtil.checkCondition(args);
}
}
class FooTest {
#Spy
#InjectMocks
private Foo foo;
#Test
void methodToTest() {
//...
when(foo.checkCondition(yourArg)).thenReturn(true);
}
}
See the Spy documentation for more details:
Option 2: factor out verification into a class:
class ArgumentVerifier {
boolean checkArgument(Object args) {
return SomeUtil.checkCondition(args);
}
}
class Foo {
private ArgumentVerifier verifier;
public void methodToTest() {
verifier.checkArgument(args); // mock the verifier as you normally would
// ....
}
}
It is possible since Mockito 3.4.0: Mocking Static Methods With Mockito
But please be aware that:
injecting remains a more explicit way of expressing dependency on another object/service, especially external api
static helper methods rarely need to be mocked (especially if they depend only on their arguments)
This limits the number of cases where mocking a static method is the tool of choice, but it is worth having it under your belt.
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.
I have a static method (foo) that calls another static method (bar). I would like to mock the response of bar in my test. Is this possible with PowerMockito or another tool? the only results I can find are for mocking statics inside of non-static methods.
public class SomeClass {
static List<String> foo() {
...
int barResult = bar();
...
}
static int bar() {
// make a database call
return DAO.getDao().runQuery();
}
}
And my test will call it like:
#RunWith(PowerMockRunner.class)
public class SomeClassTest {
#PrepareForTest(SomeClass.class)
#Test
public void fooTest() {
List<String> actualResult = SomeClass.foo();
assertTrue(...);
}
}
Am I going to have to mock the internals of bar? So mock the DAO?
You can't do that.
Only PowerMock allows you to mock static methods. But that works by "erasing" all static things within that class that gets "prepared" for testing by PowerMock.
If you were talking about ordinary methods, you could be going for Mockito spies, as those allow for partial mockings.
And just for the record: simply avoid using static, as using it leads to "hard to test" code.
In other words: instead of using the big ugly powermock hammer to "fix" your design problems... Consider fixing your broken design instead and thereby avoiding the need for PowerMock altogether!
And for the record: yes, you could solve your problem by mocking that static call on the DAO class (then you can control what bar() does indirectly. But again: that would just mean to put the "I tested it" label on code that should be reworked instead.
You can do:
#RunWith(PowerMockRunner.class)
#PrepareForTest({SomeClass.class, DAO.class})
public class SomeClassTest {
#Test
public void fooTest() {
PowerMockito.mockStatic(DAO.class);
Mockito.when(DAO.getDao().runQuery()).return(..);
List<String> actualResult = SomeClass.foo();
assertTrue(...);
}
}
I'm trying to mock private static method anotherMethod(). See code below
public class Util {
public static String method(){
return anotherMethod();
}
private static String anotherMethod() {
throw new RuntimeException(); // logic was replaced with exception.
}
}
Here is me test code
#PrepareForTest(Util.class)
public class UtilTest extends PowerMockTestCase {
#Test
public void should_prevent_invoking_of_private_method_but_return_result_of_it() throws Exception {
PowerMockito.mockStatic(Util.class);
PowerMockito.when(Util.class, "anotherMethod").thenReturn("abc");
String retrieved = Util.method();
assertNotNull(retrieved);
assertEquals(retrieved, "abc");
}
}
But every tile I run it I get this exception
java.lang.AssertionError: expected object to not be null
I suppose that I'm doing something wrong with mocking stuff. Any ideas how can I fix it?
To to this, you can use PowerMockito.spy(...) and PowerMockito.doReturn(...).
Moreover, you have to specify the PowerMock runner at your test class, and prepare the class for testing, as follows:
#PrepareForTest(Util.class)
#RunWith(PowerMockRunner.class)
public class UtilTest {
#Test
public void testMethod() throws Exception {
PowerMockito.spy(Util.class);
PowerMockito.doReturn("abc").when(Util.class, "anotherMethod");
String retrieved = Util.method();
Assert.assertNotNull(retrieved);
Assert.assertEquals(retrieved, "abc");
}
}
Hope it helps you.
If anotherMethod() takes any argument as anotherMethod(parameter), the correct invocation of the method will be:
PowerMockito.doReturn("abc").when(Util.class, "anotherMethod", parameter);
I'm not sure what version of PowerMock you are using, but with the later version, you should be using #RunWith(PowerMockRunner.class)
#PrepareForTest(Util.class)
Saying this, I find using PowerMock to be really problematic and a sure sign of a poor design. If you have the time/opportunity to change the design, I would try and do that first.
I'm trying something similar to this, and only one of the #Before methods gets called:
public abstract class ControllerBase extends Controller {
#Before
static void foo() {
// this actually gets called
}
}
public class ConcreteController extends ControllerBase {
#Before
static void bar() {
// This DOES NOT get called
}
public static void index() {
render();
}
}
Is this a bug, feature, or something I'm doing wrong?
You're trying to do something weird. And I think your example doesn't match your question. Did you mean to implement ConcreteController on ControllerBase? Rather than both of them extending on Controller?
The #before tag is a concrete class tag. Only the one in the concrete class will get executed.
You can #override the original function, but I don't think that's what you were looking for.
The best way to get what you want is to remove #before from the abstract and from the concrete function call the implemented function you want to run.
public abstract class ControllerBase extends Controller {
static void foo() {
// this actually gets called
}
}
public static class ConcreteController extends Controller {
#Before
static void bar() {
foo();
// This DOES NOT get called
}
public static void index() {
render();
}
}
Yes, Play! will call all the methods in the inheritance hiererchy annotated with #Before.
The problem I ran into was that the #Before I was using was actually org.junit.Before instead of play.mvc.Before !