13

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.

kayahr
  • 20,913
  • 29
  • 99
  • 147

3 Answers3

9

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());
    }
}
kayahr
  • 20,913
  • 29
  • 99
  • 147
3

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());
    }
}
schnatterer
  • 7,525
  • 7
  • 61
  • 80
Rogério
  • 16,171
  • 2
  • 50
  • 63
1

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.

卢声远 Shengyuan Lu
  • 31,208
  • 22
  • 85
  • 130
  • 3
    Dependency injection is a nice thing for code re-use and modularity but if that's not needed then why should I increase the complexity and loosen the API of my classes just for testability? But that's not the point here. So let's say I can't change the test subject so I can't extract the native methods into an interface. – kayahr Feb 07 '11 at 06:24
  • you're not actually increasing the complexity by doing this. your just hiding complexity by NOT doing this. you should be designing for testability to begin with – Will Apr 21 '15 at 19:34