Тестирование кода, который вызывает собственные методы

У меня есть класс вроде этого:

public final class Foo
{
    public native int getBar();

    public String toString()
    {
        return "Bar: " + getBar();
    }
}

Обратите внимание, что getBar() реализуется с JNI и что класс является окончательным. Я хочу написать тест junit для тестирования метода toString(). Для этого мне нужно высмеять метод getBar(), а затем запустить исходный метод toString() для проверки вывода.

Моя первая мысль заключалась в том, что это должно быть невозможно, но затем я нашел PowerMock, который поддерживает тестирование финальных классов и собственных методов в соответствии с функцией список. Но пока у меня не было успеха. Лучшее, что мне удалось, это насмехаться над полным классом, но затем тест протестировал смеющийся метод toString() вместо реального, который не имеет большого смысла.

Итак, как я могу использовать PowerMock для тестирования этого метода toString() сверху? Я предпочитаю использовать PowerMock с Mockito, но если это невозможно, у меня нет проблем с использованием EasyMock.

Ответ 1

Нашел. То, как я это делал, было правильным. Единственное, что я пропустил, было то, что макет вызывал оригинальный метод при вызове toString(). Поэтому он работает следующим образом:

@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

Или используйте JMockit с динамическим частичным издевательством:

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

Или используйте Шаблон стратегии:

    public final class Foo
    {
        public IBarStrategy barStrategy;

        ......
    }

    interface IBarStrategy{
        int getBar();
    }

Когда unit test, введите экземпляр mock IBarStrategy, затем вы можете проверить класс Foo.