Replacing PowerMock's #PrepareForTest programmatically? - unit-testing

I am using PowerMock to mock static methods in junit tests, typically done as follows:
#RunWith(PowerMockRunner.class)
#PrepareForTest({Foo.class,Bar.class})
public class SomeUnitTest {
#Before
public void setUpTest() {
setUpFoo();
setUpBar();
}
private void setUpFoo() {
mockStatic(Foo.class);
when(Foo.someStaticMethod()).thenReturn(1);
}
private void setUpBar() {
mockStatic(Bar.class);
when(Bar.someStaticMethod()).thenReturn(2);
}
#Test
public void someTestCase() {
...
}
}
This works fine, but I'm finding that specifying the #PrepareForTest annotation is preventing me from making my testing API flexible.
What I'd like to do is something like the following:
public class MockLibraryOne {
public static void setUpLibraryOne() {
setUpFoo();
setUpBar();
}
private static void setUpFoo() {
mockStatic(Foo.class);
when(Foo.someStaticMethod()).thenReturn(1);
}
private static void setUpBar() {
mockStatic(Bar.class);
when(Bar.someStaticMethod()).thenReturn(2);
}
}
#RunWith(PowerMockRunner.class)
public class SomeUnitTest {
#Before
public void setUpTest() {
MockLibraryOne.setUpLibraryOne();
}
#Test
public void someTestCase() {
...
}
}
Here my unit test has a dependency on LibraryOne, but it does not know which classes LibraryOne depends on, so it does not know which classes to add to the #PrepareForTest annotation.
I could make SomeUnitTest extend MockLibraryOne and add the #PrepareForTest annotation to the MockLibraryOne class, but I will have dependencies on more than just MockLibraryOne in other unit tests, so inheritance is not a general solution.
Is there some way of programmatically preparing a class for testing under PowerMock, instead of using the #PrepareForTest annotation? For example, something like the following:
public class MockLibraryOne {
public static void setUpLibraryOne() {
setUpFoo();
setUpBar();
}
private static void setUpFoo() {
prepareForTest(Foo.class);
mockStatic(Foo.class);
when(Foo.someStaticMethod()).thenReturn(1);
}
private static void setUpBar() {
prepareForTest(Bar.class);
mockStatic(Bar.class);
when(Bar.someStaticMethod()).thenReturn(2);
}
}
I guess it would be nice if PowerMockRunner processed the #PrepareForTest annotation a little differently: for each specified class, it should not only add that class (and its hierarchy) to the list of classes to prepare for mocking, but then examine that class to see if it has any #PrepareForTest annotations as well:
#RunWith(PowerMockRunner.class)
#PrepareForTest({MockLibraryOne.class})
public class SomeUnitTest {
...
}
#PrepareForTest({Foo.class,Bar.class})
public class MockLibraryOne {
...
}
}
So in this the #PrepareForTest annotation on SomeUnitTest would find MockLibraryOne, and the #PrepareForTest annotation there would drag in Foo.class and Bar.class as well.
So perhaps writing my own test runner to replace PowerMockRunner may be a solution.
Or perhaps there's a simpler solution, using PowerMockAgent class, for example?
edit: Mock Policies may be one solution: https://code.google.com/p/powermock/wiki/MockPolicies
edit: Mock Policies works with PowerMockRunner but not (it seems) with PowerMockRule (which I sometimes require due to class loader issues).

What you try to achieve will not work.
The problem is that powermock must rewrite the client class's code to intercept the static invocation and it can't do this after the class is loaded. Thus it can only prepare a class for test before it is loaded.
Let's assume you want to mock the System.currentTimeMillis invocation in the following simple class.
class SystemClock {
public long getTime() {
return System.currentTimeMillis();
}
}
Powermock will not change the code of java.lang.System.currentTimeMillis, because it can't. Instead it changes the SystemClock's byte code so that it does not invoke System.currentTimeMillis anymore. Instead it invokes some other object that belong to powermock.
This is how powermock get's full control over the return value and allows you to write a test like this:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ SystemClock.class })
public class PowerMockitoTest {
#Test
public void systemTimeMillis() {
SystemClock systemClock = new SystemClock();
PowerMockito.mockStatic(System.class);
PowerMockito.when(System.currentTimeMillis()).thenReturn(12345L);
long time = systemClock.getTime();
assertEquals(12345L, time);
}
}
You can see that powermock has rewritten the client class in the stacktrace of your debugger. Set a breakpoint at SystemClock.getTime and step into the invoked method.
As you can see SystemClock invokes a MockGateway.
If you take a look at the variables on the stack of the MockGateway invocation, you can see how the original System.currentTimeMillis method is handled.

Perhaps you're looking for a mock policy?

Could you help this (taken from documentation)?
You can also prepare whole packages for test by using wildcards:
#PrepareForTest(fullyQualifiedNames="com.mypackage.*")
So you can add the whole library to your prepare...

Why do you even want to mock static methods? Why not wrap those static methods in a class that you can mock with mockito?
class FooWraper {
void someMethod() {
Foo.someStaticMethod()
}
}
and then you can create a mock of your FooWraper. No need to use Powermock at all...

Related

Apply a JUnit Custom #Rule a particular test method

Can I run a custom rule only for a particular test method in a test class?
public class TestClassExample
{
#Rule
public CustomRuleForOneEqualsOne customRuleForOneEqualsOne = new CustomRuleForOneEqualsOne();
#Test
public void test_OneEqualsOne()
{
assertEquals(1, 1);
}
#Test
public void test_TwoEqualsTwo()
{
assertEquals(2, 2);
}
}
In the above test class can I use my customRuleForOneEqualsOne rule be used only for test method test_OneEqualsOne and not for test_TwoEqualsTwo.
I've seen other solutions on Stack Overflow:
Move the two test methods into different class [say this option is not possible for particulr scenario] (or)
JUnit: #Before only for some test methods? as described by this post
I can somehow use the test method name and skip over the execution of the rule
but a drawback of this approach would be, each time I use the rule in a specific class for a specific set of methods, I need to add all those method names to a list to see if they are found, to determine the execution of the rest of the logic.
Is there any way to use a custom rule in a test class for a particular set of test methods while ignoring them for the other test methods in the same test class?
For the best of my knowledge, #Rule applies to all tests. Therefore, if you need #Rule to be used in a single #Test method only, don't use #Rule. In that case, your code would look like this:
public class TestClassExample {
#Test
public void test_OneEqualsOne() {
CustomRuleForOneEqualsOne customRuleForOneEqualsOne = new CustomRuleForOneEqualsOne();
// use customRuleForOneEqualsOne
}
#Test
public void test_TwoEqualsTwo() {
assertEquals(2, 2);
}
}

Unit testing a started Service which has a few fields injected into it?

I am a Dagger newbie.
TL;DR:
If an Android Service has any fields injected into it using Dagger, then in order to actually perform the injection, I need to have an instance of that Service.
In Robolectric tests, this corresponds to MyService service = Robolectric.buildService(MyService.class).get(). And then, objectGraph.inject(service);
However, rest of the code that actually starts MyService still uses context.startService(context, MyService.class);.
Question: What is the idiomatic way in Dagger to address this mismatch?
Let's say I have a Service as follows:
public class MyService {
#Inject Parser parser;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
String data = intent.getStringExtra("data_to_be_parsed");
parser.parse(data);
}
}
Elsewhere in my code, I have an ApiClient class that does this:
public class ApiClient{
public static void parseInBackground(Context context, String data){
//This service does not have its fields injected
context.startService(new Intent(context, MyService.class).putExtra("data_to_be_parsed", data));
}
}
That parseInBackground method will be called from an Activity in response to user interaction.
Now, I'm following TDD and hence, I haven't yet written the Application Module for this. Here's the test module:
#Module(injects = MyService.class)
public class TestModule {
#Provides #Singleton Parser provideParser(){
return new MockParser();
}
}
And finally, the test case:
#RunWith(Robolectric.class)
public class ApiTest {
#Test
public void parseInBackground_ParsesCorrectly(){
//This service has its fields injected
MyService service = Robolectric.buildService(MyService.class).get();
ObjectGraph.create(new TestModule()).inject(service);
ApiClient.parseInBackground(Robolectric.application, "<user><name>droid</name></user>");
//Asserts here
}
}
As you can see, in the test, I retrieve an instance of the service and then inject the MockParser into it. However, the ApiClient class directly starts the service using an Intent. I don't have a chance to perform the injection.
I am aware that I can have MyService perform an injection on itself:
public void onCreate(){
ObjectGraph.create(new TestModule()).inject(this);
}
But then, I am hardcoding the TestModule here.
Is there an existing idiom in Dagger to set up dependencies for such situations?
It's the wrong way to hardcode your modules either in tests or in services. Better approach is to perform creation via your custom Application object which in turn will hold singleton ObjectGraph object. For example:
// in MyService class
#Override public void onCreate() {
super.onCreate();
MyApp.from(context).inject(this);
}
// in MyApp class
public static MyApp from(Context context) {
return (MyApp) context.getApplicationContext();
}
//...
private ObjectGraph objectGraph;
#Override public void onCreate() {
// Perform Injection
objectGraph = ObjectGraph.create(getModules());
objectGraph.inject(this);
}
public void inject(Object object) {
objectGraph.inject(object);
}
protected Object[] getModules() {
// return concrete modules based on build type or any other conditions.
}
Alternatively, you can refactor last method out into separate class and make different implementations for different flavors or build types. Also you may want to set overrides=true in your TestModule's annotation.

How do I mock a static method in final class

I have some code that has a static method inside a final class. I was trying to mock that method. I have tried doing a few things..
public final Class Class1{
public static void doSomething(){
}
}
How can I mock doSomething()? I have tried..
Class1 c1=PowerMockito.mock(Class1.class)
PowerMockito.mockSatic(Class1.class);
Mockito.doNothing().when(c1).doSomething();
This gives me an error:
org.mockito.exceptions.misusing.UnfinishedStubbingException:
Unfinished stubbing detected here:
-> at com.cerner.devcenter.wag.textHandler.AssessmentFactory_Test.testGetGradeReport_HTMLAssessment(AssessmentFactory_Test.java:63)
E.g. thenReturn() may be missing.
Examples of correct stubbing:
when(mock.isOk()).thenReturn(true);
when(mock.isOk()).thenThrow(exception);
doThrow(exception).when(mock).someVoidMethod();
Hints:
1. missing thenReturn()
2. you are trying to stub a final method, you naughty developer!
at org.powermock.api.mockito.internal.invocation.MockitoMethodInvocationControl.performIntercept(MockitoMethodInvocationControl.java:260)
Most used testing framework is JUnit 4. So if you are using it you need to annotate test class with:
#RunWith( PowerMockRunner.class )
#PrepareForTest( Class1.class )
Than
PowerMockito.mockSatic(Class1.class);
Mockito.doNothing().when(c1).doSomething();
Mockito.when(Class1.doSomething()).thenReturn(fakedValue);
// call of static method is required to mock it
PowerMockito.doNothing().when(Class1.class);
Class1.doSomething();
I use PowerMock. It let's you do things Mockito can't do.
https://github.com/powermock/powermock/wiki
#RunWith(PowerMockRunner.class)
#PrepareForTest(StaticClass.class)
public class StaticTest {
#Before
public void setUp() {
PowerMockito.mockStatic(Bukkit.class);
//When a static method with no arguments is called.
when(StaticClass.callMethod1()).thenReturn(value);
//When a static method with an argument is called.
when(StaticClass.callMethod2(argument)).thenReturn(value2);
//Use when you don't care what the argument is..
//use Mockito.anyInt(), Mockito.anyDouble(), etc.
when(StaticClass.callMethod3(Mockito.anyString())).thenReturn(value3);
}
#Test
public void VerifyStaticMethodsWork() {
assertEquals(value, StaticClass.callMethod1());
assertEquals(value2, StaticClass.callMethod2(argument));
assertEquals(value3, StaticClass.callMethod3("Hello"));
}
}

Testing private methods in java using Powermockito

I am using PowerMockito and jUnit to write unit test cases.
public class Foo {
private String resolveApplicationId() {
return "testApplication";
}
}
Here is my test case
#RunWith(PowerMockRunner.class)
#PrepareForTest(Foo.class)
public class test{
#Before
public void prepareTest() {
foo = PowerMockito.spy(new Foo());
}
#Test
public void checkApplicationIdIsResolved() throws Exception {
PowerMockito.doNothing().when(foo, "myPrivateMethod");
PowerMockito.verifyPrivate(foo).invoke("myPrivateMethod");
//Assert Here the returned value
}
}
Please tell me
1. how can I assert the value returned by the method when it is called
2. how can I call the private method
3. if not then what actually I verify when I write test case for private methods.
Thanks.
Testing private method does not differ from testing public method. If there is no external dependencies you even don't need to create and use any mocks. The only problem is with invocation of the private method from test. This is described here or you may use spring utils.
So you don't need to mock the method you are testing. You only require to mock other objects which are not tested in this particular test. So you test would look like
#Test
public void checkApplicationIdIsResolved() throws Exception {
// makeResolveIdAccessible();
// if needed setup mocks for objects used in resolveApplicationId
assertEquals(expectedApplicationId, foo.resolveApplicationId())
}

Unit test for EJB with #PostConstruct method

Consider the following sample code:
#Stateless
public class MyBean {
private SomeHelper helper;
private long someField;
#PostConstruct
void init() {
helper = new SomeHelper();
someField = initSomeField();
}
long initSomeField() {
// perform initialization
}
public void methodToTest() {
helper.someMethod();
long tmp = 3 + someField;
}
}
And here is the test template, that I always use
public class MyBeanTest {
#Spy
#InjectMocks
private MyBean testSubject;
#Mock
private SomeHelper mockedHelper;
#Before
public void before() {
MockitoAnnotations.initMocks(this);
doReturn(1L).when(testSubject).initSomeField();
}
#Test
public void test() {
testSubject.methodToTest();
// assertions
}
}
The problem with testing methodToTest is that it needs field someField to be initialized. But the initialization is done in #PostConstruct method. And I can't run this method before call to testSubject.methodToTest(), because it will re-initialize helper. Also, I don't want to manually set up all the mocks. And I don't want to use reflection to set the someField, because that would make MyBeanTest vulnerable to MyBean refactoring. Can anybody propose, maybe better design to avoid situations like this?
A few notes:
Logic in initSomeField could be quite heavy (including calls to database), so I want to initialize it only once in a #PostConstruct method.
I don't want to create a setter for this field or widen its access modifier, because that would allow unwanted changes to my field.
If your test is in the same package as your class, then you can just call initSomeField directly, since it's package private. You can either do this in each individual test method, or in your #Before method, provided it runs after initMocks.