问题
I have a class like this:
public final class Foo
{
public native int getBar();
public String toString()
{
return "Bar: " + getBar();
}
}
Please note that getBar() is implemented with JNI and that the class is final. I want to write a junit test to test the toString() method. For this I need to mock the getBar() method and then run the original toString() method to check the output.
My first thought was that this must be impossible but then I found PowerMock which supports testing final classes and native methods according to the feature list. But so far I had no success with it. The best thing I managed was mocking the complete class but then the test tested the mocked toString() method instead of the real one which doesn't make much sense.
So how can I use PowerMock to test this toString() method from above? I prefer using PowerMock with Mockito but if this is not possible I have no problem with using EasyMock instead.
回答1:
Found it. The way I was doing it was correct. The only thing I missed was telling the mock object to call the original method when toString was called(). So it works like this:
@RunWith(PowerMockRunner.class)
@PrepareForTest({ Foo.class })
public class FooTest
{
@Test
public void testToString() throws Exception
{
Foo foo = mock(Foo.class);
when(foo.getBar()).thenReturn(42);
when(foo.toString()).thenCallRealMethod();
assertEquals("Bar: 42", foo.toString());
}
}
回答2:
Or use JMockit with dynamic partial mocking:
import org.junit.*;
import mockit.*;
public class FooTest
{
@Test
public void testToString()
{
final Foo foo = new Foo();
new Expectations(foo) {{ foo.getBar(); result = 42; }};
assertEquals("Bar: 42", foo.toString());
}
}
回答3:
Or use Strategy Pattern:
public final class Foo
{
public IBarStrategy barStrategy;
......
}
interface IBarStrategy{
int getBar();
}
When unit test, inject a mock IBarStrategy
instance, then you could test class Foo
.
来源:https://stackoverflow.com/questions/4916217/testing-code-which-calls-native-methods