Основы PowerMock EasyMock - PullRequest
       60

Основы PowerMock EasyMock

4 голосов
/ 26 января 2012

Это, вероятно, вопрос PowerMock / EasyMock 101, который я не могу понять, почему. У меня есть класс C с методами

public static boolean testInner(String s) {
    return false;
}

public static boolean testOuter() {
    String x = "someValue";
    return testInner(x);
}

В моем тесте метода testOuter () я хочу убедиться, что testInner вызывается с соответствующим параметром. Для этого я делаю что-то вроде этого: [@RunWith (PowerMockRunner.class) @PrepareForTest (EmailUtil.class) объявлен на уровне класса]

EasyMock.expect(C.testInner("blabla")).andReturn(true);
PowerMock.replayAll();
boolean status = C.testOuter();
PowerMock.verifyAll();  
assertTrue(status);

Но я получаю сообщение об ошибке:

java.lang.AssertionError: 
Unexpected method call testOuter():
testInner("blabla"): expected: 1, actual: 0
    at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:45)
    at org.powermock.api.easymock.internal.invocationcontrol.EasyMockMethodInvocationControl.invoke(EasyMockMethodInvocationControl.java:95)
    at org.powermock.core.MockGateway.doMethodCall(MockGateway.java:105)
    at org.powermock.core.MockGateway.methodCall(MockGateway.java:60)
    at C.testOuter(C.java)

Я заменил фактический параметр на EasyMock.IsA (String.class), но все равно не повезло. Я почти уверен, что делаю здесь что-то принципиально глупое. Любая помощь?

Ответы [ 3 ]

13 голосов
/ 05 августа 2012

Я думаю, что здесь есть две проблемы, одна из которых связана с отсутствующим вызовом в вашем тестовом коде.Вторая связана с вашим пониманием поведенческой насмешки и разницы между полной и частичной насмешкой.

Пропущенные звонки

Кажется, вы пропускаете звонок на PowerMock.mockStatic или один из методов PowerMock.mockPartialMock (см. также this ).Первый метод будет проверять все передаваемые ему статические методы, а второй - только список предоставленных им методов.

Пример

Вот полный пример с двумя методами тестирования, которые иллюстрируют два варианта.Во-первых, мы должны аннотировать тестовый класс, используя эти две аннотации:

@RunWith(PowerMockRunner.class)
@PrepareForTest(Dummy.class)
public class DummyTest {

Первая аннотация говорит JUnit, что нужно выполнить тест с использованием PowerMockRunner.Вторая аннотация говорит PowerMock подготовиться к макету класса Dummy.

Full Static Mock

Далее мы рассмотрим пример, где все статические методы из класса Dummy подвергаются макету.,Что это значит?По сути, это означает, что мы хотели бы заменить фактическую реализацию поддельными (ложными).Как должна вести себя эта ложная реализация?Это то, что мы указываем в ожидании.

Таким образом, в методе testStaticMock мы говорим EasyMock дать нам поддельную реализацию двух методов.Нам понравится, что подделка Dummy.testOuter просто вернет true.И нам нужно, чтобы фальшивый Dummy.testInner возвращал true при передаче аргумента "bb".Обратите внимание, что когда эти макеты активированы (PowerMock.replayAll), тестовый код будет запускать только поддельные методы, а не фактическую реализацию - это, кажется, источник вашей путаницы.Я еще скажу об этом позже.

    @Test
    public void testStaticMock() {
        mockStatic(Dummy.class);
        EasyMock.expect(Dummy.testOuter()).andReturn(true);
        EasyMock.expect(Dummy.testInner("bb")).andReturn(true);
        replayAll();
        boolean status = Dummy.testOuter();
        Assert.assertTrue(status);
        status = Dummy.testInner("bb");
        Assert.assertTrue(status);
        verifyAll();
    }

Partial Static Mock

Вот еще один тест, в котором мы не высмеиваем все методы, а только те, которые мы передаем mockStaticPartial.Ниже мы сообщаем PowerMock, что хотим только смоделировать метод Dummy.testInner.Таким образом, часть Dummy является поддельной, а остальная часть - тестируемым классом.

    @Test
    public void testPartialStaticMock() {
        mockStaticPartial(Dummy.class, "testInner");
        EasyMock.expect(Dummy.testInner("someValue")).andReturn(true);
        replayAll();
        boolean status = Dummy.testOuter();
        verifyAll();
        Assert.assertTrue(status);
    }
}

И пусть смоделированный класс Dummy будет определен следующим образом:

public class Dummy {
    public static boolean testInner(String s) {
        return false;
    }

    public static boolean testOuter() {
        String x = "someValue";
        return testInner(x);
    }
}

Полное высмеивание против частичного пересмешивания

Одна вещь, которую нужно понять о полном статическом пересмешиванииявляется то, что все статические методы являются издевательскими.Таким образом, метод testOuter будет заменен на смоделированную версию и будет иметь такую ​​реализацию, как:

    public static boolean testOuter() {
        return true; //or whatever value is provided in the expectation
    }

Таким образом, мы не должны ожидать, что смоделированная версия будет вызывать методы, которые делает фактическая реализация,Мы не хотели заботиться о внутренностях метода.По этой причине мы решили все-таки насмехаться над ней - заменить ее внутреннюю часть на игрушечную реализацию, определяемую только ожиданиями, которые мы для нее установили.

С другой стороны, когда мы делали частичное издевательство, мы не издевались testOuter, поэтому мы вызывали его фактическую реализацию.

1 голос
/ 26 января 2012

Вы только говорите EasyMock ожидать вызова testInner (), а не testOuter ().

 Unexpected method call testOuter():

Попробовал это:

EasyMock.expect(C.testInner("blabla")).andReturn(true);
EasyMock.expect(C.testOuter());
PowerMock.replayAll();
0 голосов
/ 17 мая 2018

Ответ на пример потока вызовов для макетирования статической функции void с помощью mockStaticPartial ().

PowerMock.mockStaticPartial(Sample.class, "test");
Sample.test();
EasyMock.expectLastCall();
PowerMock.replay(Sample.class);

Позже в тесте, если вы называете что-то вроде:

assertFalse(Sample.returnFalseBool());

Тест будет вызывать реальный метод, так как в этом случае была проверена только функция test ().

Отказ от ответственности : я знаю, что это, возможно, не лучшее место, чтобы добавить этот ответ, но соединение нескольких других ответов на различные связанные вопросы помогло мне придумать этот ответ, посчитав необходимым это где-то.

...