Reputation: 21
I am able to mock a constructor call using powermock from inside a class which I want to test. This works when I add the class I want to test in @PrepareForTest. But once I add my class there, even when the test cases pass, the coverage is being shown as 0 in the coverage plugin.
When I remove my class from @PrepareForTest
, of course, coverage starts showing up for other test cases but the test case in which I have to mock constructor call fails. Not sure what to do about this.
Class A
{
MyObject o;
A(){
//some other code
o = new MyObject();
//some other code
}
public void process(){
//some code
}
@RunWith(PowerMockRunner.class)
@PrepareForTest(A.class)
Class TestA{
@Test
public void test1()
{
MyObject mocked = Mockito.mock(MyObject.class);
PowerMockito.whenNew(MyObject.class).withNoArguments().thenReturn(mocked);
A a = new A();
a.process();
//Assert as per test case
}
}
In coverage tool, coverage shows as 0 however, unit test passes and I checked in debug mode that it was covering all the statements of class A.
Upvotes: 0
Views: 2361
Reputation: 140447
In coverage tool, coverage shows as 0 however, unit test passes and I checked in debug mode that it was covering all the statements of class A.
Coverage tools rely on manipulating the executed byte code.
So does PowerMock, when you mock static/new.
This can quickly lead to all sorts of problems. For JaCoCo, there seems to be a solution around offline instrumentation. Where, I also remember: some other person asked about that some time back, and in the end gave up, because he couldn't get "offline instrumentation" to work either.
For any other framework, I have to repeat old advice: consider to invest your time to learn how to write easy-to-test code. Because if you would do that, you would not need to use PowerMock(ito) in order to test it.
Your code is hard-to-test because of that new()
statement in the constructor. Simply don't do that. Either use dependency injection via @InjectMocks, or have a test-only constructor that takes the required object.
Long story sort: when you write your own, new code, and you think you need PowerMock to test it, then you are doing something wrong.
Upvotes: 2
Reputation: 26522
I think you can do without Powermock here. If you Spy on class A
and mock the getter you should end up with the same result and most likely have your coverage correct:
@Test
public void test1(){
MyObject mocked = Mockito.mock(MyObject.class);
A spyA = Mockito.spy(new A());
doReturn(mocked).when(spyA).getMyObject();
...
}
Upvotes: 0