6

I am currently stumbling in JUnit testing and need some help. So I got this class with static methods which will refactor some objects. For simplification's sake I have made a small example. This is my Factory class:

class Factory {

    public static String factorObject() throws Exception {
        String s = "Hello Mary Lou";
        checkString(s);
        return s;
    }

    private static void checkString(String s) throws Exception {
        throw new Exception();
    }
}

And this is my Test class:

@RunWith(PowerMockRunner.class)
@PrepareForTest({ Factory.class })        
public class Tests extends TestCase {

    public void testFactory() throws Exception {

        mockStatic(Factory.class);
        suppress(method(Factory.class, "checkString"));
        String s = Factory.factorObject();
        assertEquals("Hello Mary Lou", s);
    }
}

Basically what I tried to achieve is that the private method checkString() should be suppressed (so the Exception is not thrown), and also need to verify that the method checkString() was actually called in the method factorObject().

UPDATED: The suppression works correctly with the following code:

suppress(method(Factory.class, "checkString", String.class));
String s = Factory.factorObject();

... however it returns me NULL for the String "s". Why is that?

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Malvin
  • 859
  • 2
  • 11
  • 19
  • IMHO you have taken the tool too far. The idea of mocking the class under test is something that is discouraged. Instead you should pass values to your method under test that will pass and fail validation by check string. This allows you to fully test the method under test without relying on its implementation. What you are designing are brittle tests. – John B May 09 '13 at 11:09
  • I agree with you, but currently there is no way to change the existing code, therefore verification must happen a little bit more complicated. – Malvin May 09 '13 at 11:55

2 Answers2

10

Ok, I finally found the solution to all problems. If anyone stumbles across similar issues here is the code:

import junit.framework.TestCase;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.times;
import static org.powermock.api.support.membermodification.MemberModifier.suppress;
import static org.powermock.api.support.membermodification.MemberMatcher.method;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.verifyPrivate;

@RunWith(PowerMockRunner.class)
@PrepareForTest(Factory.class)
public class Tests extends TestCase {

    public void testFactory() throws Exception {

        mockStatic(Factory.class, Mockito.CALLS_REAL_METHODS);
        suppress(method(Factory.class, "checkString", String.class));
        String s = Factory.factorObject();
        verifyPrivate(Factory.class, times(1)).invoke("checkString", anyString()); 
        assertEquals("Hello Mary Lou", s);      
    }
}
Malvin
  • 859
  • 2
  • 11
  • 19
  • Would you provide the classes of the static method to make this answer more clear? Specifically `mockStatic`, `suppress`, `method` and `verifyPrivate`? – John B May 09 '13 at 12:54
  • For testing purposes I also used the standalone packages with all dependencies: http://code.google.com/p/powermock/downloads/detail?name=powermock-mockito-junit-1.5.zip&can=2&q= If you use Maven you might need less. – Malvin May 09 '13 at 13:40
  • This helped me a lot. Thanks a lot for giving a detailed code outline of how to make it work. – Akshay Mar 15 '16 at 20:49
4

Yo can do it like:

PowerMockito.doNothing().when(Factory.class,"checkString");

For more details you can visit :
http://powermock.googlecode.com/svn/docs/powermock-1.3.7/apidocs/org/powermock/api/mockito/PowerMockito.html

Edit:

ClassToTest spy = spy(new ClassToTest ());
doNothing().when(spy).methodToSkip();
spy.methodToTest();
Shreyos Adikari
  • 12,348
  • 19
  • 73
  • 82
  • Hello, I tried it but get an IllegalArgumentException. This is really weird, something in this whole setup is strange, although it looks simple :( – Malvin May 09 '13 at 10:48
  • I tried it now like this: mockStatic(Factory.class); Factory spy = spy(new Factory()); PowerMockito.doNothing().when(Factory.class,"checkString", Mockito.any(String.class)); String s = spy.factorObject();
    But now it returns me a for String s. I don't get it...
    – Malvin May 09 '13 at 11:51
  • The suppression seems to work though. When I do suppress(method(Factory.class, "checkString", String.class)); Unfortunately I also get a instead of the String declared in the method. But at least the private Method is suppressed obviously. But still why is the string suddenly null? – Malvin May 09 '13 at 12:02