Verify private static method on final class gets called using PowerMockito - java

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
...
}
}

Related

Java MockedStatic method is still called

So I'm using MockedStatic<> to mock a static method but it seems like the item inside is still getting called? If this is the case, what's the point of mocking it? I have the following setup:
Object being tested:
public class ObjectBeingTested {
public void methodBeingTested() {
Object obj = ObjectInQuestion.getInstance(new Object(), "abc");
// do stuff with obj
}
}
The object with static method:
public class ObjectInQuestion {
public static ObjectInQuestion getInstance(Object obj, String blah) {
someLocalVar = new FileRequiredObject();
// we get NullPointerException here cuz in test env, no files found
}
private ObjectInQuestion() {
// private constructor to make people use getInstance
}
}
Test code:
public class MyTestClass {
MockedStatic<SomeClass> mySomeClass;
#Mock ObjectInQuestion mMockedObjectInQuestion;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
mySomeClass = mockStatic(SomeClass.class);
when(SomeClass.getInstance(any(), anyString()).thenReturn(mMockedObjectInQuestion);
}
#After
public void tearDown() {
mySomeClass.close();
}
}
My questions are the following:
Why calling ObjectInQuestion.getInstance() in the test class, it's totally fine but when it's being called from ObjectBeingTested, it runs the real construction?
I tried to use mockConstruction on FileRequiredObject, it still actually construct the object ... why?
You're using the wrong syntax for stubbing the static method. You want something like
mySomeClass.when(
()->SomeClass.getInstance(any(), anyString()))
.thenReturn(mMockedObjectInQuestion);
More information available here
Assuming MockedStatic<SomeClass> mySomeClass; is actually MockedStatic<ObjectInQuestion> mySomeClass;, I would try to simplify the setup using a classic try block.
In any case, sharing the actual test method might be able to shine some light. ;)

Check that static void method was called, with Mockito

There are considerable answers around, that seem to address this topic, but somehow it is never working out for me. I must be making some mistake, somewhere.
I have this class.
public class myClass {
public static void myEdit(boolean flag) throws Exception {
if (flag) {
System.out.println("Wow!");
} else {
PortalBL.mySave(flag);
}
}
public static void mySave(boolean wtv) throws Exception {
System.out.println("Doesn't matter");
}
}
I want to write a simple unit test, where I call myEdit, with flag = false. I just want the test to pass if it confirms that the PortaBL.mySave was called. I don't want it to be executed, I just want to verify if it was called.
I am trying to do it like this:
#Test
public void myTest() throws Exception {
try (MockedStatic<PortalBL> mock = Mockito.mockStatic(PortalBL.class)) {
mock.when(() -> PortalBL.mySave(anyBoolean())).thenAnswer((Answer<Void>) invocation -> null);
PortalBL.myEdit(false);
mock.verify(() -> PortalBL.mySave(anyBoolean()));
}
}
The idea would be to mock the static method, so that I can handle it without executing it and later verify that it was called, when I call PortalBL.myEdit
I believe that the class is badly written. It shouldn't be static method, I should be instantiating this class as an object and carry on. But, let's say that we are determined to test this particular scenario, as it is. Is it possible?
Btw, when I execute the PortaBL.myEdit(false) line, it isn't truly executed. I believe it is because the machine is thinking it is a mock, and doesn't know what to do with it when it is called..

PowerMockito.verifyStatic method does not work

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

How should I mock out a single method inside an object I'm trying to test?

I have a problem with a class that I am testing where in almost every method I want to test, one of the first things each method does is call this one specific method. This method that is called once by all of these other methods takes a long time to execute. I don't want to have to wait for this every time I run my tests, it really is just a huge waste of time.
I attempted to #Spy the method using Mocktio, but I ran into problems because the really long method doesn't return anything. Can someone suggest a good way to mock out a single method inside a class I am trying to test?
Example:
public class myClass {
public void methodOne() {
reallyLongMethod();
// More code
}
public void methodTwo() {
reallyLongMethod();
// More code
}
.
.
.
public void methodN() {
reallyLongMethod();
// More code
}
public void reallyLongMethod() {
}
}
This is the class I am trying to test. I want to test all of the 'methodX()' methods. I don't want to run reallyLongMethod everysingle time however.
So, is there a way to use Mockito 'Spy' to stub out reallyLongMethod()? Even though it doesn'treturn anything?
You can use a Spy with doNothing(), but make sure you use the spy during the test. Mockito spies copy the original, instead of delegating to it.
#RunWith(MockitoJUnitRunner.class)
public class YourTest {
// Option 1:
// #Spy MyClass myClass = new MyClass();
// Option 2 (see #Before method)
MyClass myClass;
#Before public void ignoreReallyLongMethod() {
myClass = spy(new MyClass()); // discard original
doNothing().when(myClass).reallyLongMethod();
}
#Test public void methodOneWorks() {
myClass.methodOne(); // you're using the spy here
assertEquals(42, myClass.getFoo());
}
}
Though this does evoke a code smell, don't mock or stub the class under test, as long as you're careful to test the method behavior (methodOne) and not the stubbed behavior (reallyLongMethod) you'll be good to go. If you do want to test reallyLongMethod you'll want to use a different object instance or else you'll "test" the doNothing() call alone. Do bear in mind that if reallyLongMethod and your other methods have any negative interactions, these tests won't tell you about that.
By the way, you can also do the equivalent without using Mockito, which may make a little clearer what you are or aren't doing with your mocks:
#RunWith(JUnit4.class)
public class YourTest {
MyClass myClass;
#Before public void createMyClass() {
myClass = new MyClass() { // create an anonymous inner class
#Override public void reallyLongMethod() {} // that does nothing here
};
}
}

How to verify method is only ever called with expected arguments?

I'd like to verify that calls against a mock only ever happen with some expected argument values, and never with anything else.
public interface ADependancy {
public void method(String parameter, String otherParameter);
}
public class Foo {
private ADependancy myHelper;
public Foo(ADependancy helper) {
this.myHelper = helper;
}
public void good() {
myHelper.method("expected","expected");
myHelper.method("expected","expected");
myHelper.method("expected","expected");
}
public void bad() {
myHelper.method("expected","expected");
myHelper.method("expected","UNexpected");
myHelper.method("expected","expected");
}
}
I tried this:
public class FooTest extends TestCase {
private ADependancy mock =mock(ADependancy.class);;
private Foo foo = new Foo(mock);
#Test
public void testGood() {
foo.good();
validateOnlyCalledWithExpected();
}
#Test
public void testBad() {
foo.bad();
validateOnlyCalledWithExpected();
}
private void validateOnlyCalledWithExpected() {
verify(mock,atLeastOnce()).method(eq("expected"),eq("expected"));
verify(mock,never()).method(not(eq("expected")),not(eq("expected")));
}
}
Expecting testBad to fail, but instead the test passes. If method only takes one parameter, this works as expected.
It was a logic mistake.
I wanted to assert that each argument is never anything but the expected value.
But instead, what I was actually asserting was that it never happens that they are ALL not the expected value.
So with the way I had it, it did not fail as desired, because in fact, some of the arguments are not not the expected value, therefore the method is never called with all the parameters not the expected value, and the verify passes.
Thus, this works for what I wanted:
private void validateOnlyCalledWithExpected() {
verify(mock,atLeastOnce()).method(eq("expected"),eq("expected"));
verify(mock,never()).method(not(eq("expected")),anyString());
verify(mock,never()).method(anyString(),not(eq("expected")));
}
You could use the verifyNoMoreInteractions static method, documented at http://docs.mockito.googlecode.com/hg/latest/org/mockito/Mockito.html#finding_redundant_invocations.
verify(mock).method(eq("expected"),eq("expected"));
verifyNoMoreInteractions(mock);
Alternatively, you could write
verify(mock).method(eq("expected"),eq("expected"));
verify(mock,never()).method(anyString(),anyString());
because the second call to verify will disregard the calls that have already been verified.

Categories

Resources