Reputation: 21
I 'm a newie in Junit-testing but I have to test some code. I think now I know the basics of it, but I still got a problem on which I couldn't find anything on the Internet:
Here's the class I want to test:
public static void methodToTest(Label l2, Label l3, User u) {
int first = MyDB.someMethod(u.anotherMethod()).size();
int second = MyDB.someOtherMethod(u).size();
if (first == 1) {
l2.setCaption("...");
}
...
}
I don't want the System to create the Integers 'first' and 'second'. Instead I just want them to be '1' so I can test if the last lines of code work properly.
MyDB is a public class with static Methods (someMethod() and someOtherMethod())
I want to test the Method methodToTest. I tried to call this method with parms and at the end compare the modified params to the expected ones.
I use Mockito and PowerMockito.
This is one of my tries:
@PrepareForTest({ClassToTest.class, MyDB.class })
@RunWith(PowerMockRunner.class)
public class Test extends PowerMockTestCase{
PowerMockito.mockStatic(MyDB.class);
PowerMockito.doReturn(1).when(MyDB.someMethod(u.anotherMethod()).size());
PowerMockito.doReturn(1).when(MyDB.someOtherMethod(u).size());
ClassToTest.methodToTest(l1, l2, u);
assertTrue(l1.equals(l3) && l2.equals(l4));
}
The exception that I get is: 'Argument passed to when() is not a mock!'
I hope anyone can help me. I passed so many hours to solve this problem, without success.
Thank you!!!
Upvotes: 1
Views: 1495
Reputation: 2826
As I mentioned in my comment, you have found that the static methods are an impediment to testing. So, I would suggest that you avoid static methods. Let's see what that might look like in your example:
You have some code you need to test..
public class ProductionClass {
public static void methodToTest(Label l2, Label l3, User u) {
int first = MyDB.someMethod(u.anotherMethod()).size();
int second = MyDB.someOtherMethod(u).size();
if (first == 1) {
l2.setCaption("...");
}
...
}
}
First things first..make the static method of the production class an instance method:
public class ProductionClass {
public void methodToTest(Label l2, Label l3, User u) { // removed "static"
int first = MyDB.someMethod(u.anotherMethod()).size();
int second = MyDB.someOtherMethod(u).size();
if (first == 1) {
l2.setCaption("...");
}
...
}
}
Ok, so you still have coupling to static methods on MyDB. Getting rid of that one static method just made your production class a lot more testable. Here's how..you can do a couple of extract method refactorings like this:
public class ProductionClass {
public void methodToTest(Label l2, Label l3, User u) {
int first = getFirst();
int second = getSecond();
if (first == 1) {
l2.setCaption("...");
}
...
}
int getFirst() {
return MyDB.someMethod(u.anotherMethod()).size();
}
int getSecond() {
return MyDB.someOtherMethod(u).size();
}
}
Now you can easily subclass that production class and override (or partial mock, if you prefer) the methods that you want to futz with..
public class TestableProductionClass extends ProductionClass {
@Override
int getFirst() {
return 1;
}
@Override
int getSecond() {
return 1;
}
}
Wouldn't make it any harder than it needs to be and introducing PowerMock tends to add complexity that I'd rather not deal with. YMMV. Good luck!
Upvotes: 1