1

я (еще) пытается проверить, если bar(Alpha, Baz) называется bar(Xray, Baz) использованием PowerMockito (как bar(Xray, Baz) является private) - фактически не называя позже, учитывая мой MCVE класс Foo ниже. (Я прошел через тот же класс earlier, со всеми методами в Foo быть public - в случае, если у вас есть дежавю ...)PowerMockito бросает NullPointerException при попытке окурок личное перегруженный метод

public class Foo { 
    private String bar(Xray xray, Baz baz) { 
     return "Xray"; 
    } 

    private String bar(Zulu zulu, Baz baz) { 
     return "Zulu"; 
    } 

    public String bar(Alpha alpha, Baz baz) { 
     if(alpha.get() instanceof Xray) { 
      return bar((Xray)alpha.get(), baz); 
     } else if(alpha.get() instanceof Zulu) { 
      return bar((Zulu)alpha.get(), baz); 
     } else { 
      return null; 
     } 
    } 
} 

Когда я пытаюсь запустить тест ниже, я получаю NPE от PowerMock:

@RunWith(PowerMockRunner.class) 
// @PrepareOnlyThisForTest(Foo.class) // we aren't looking at the byte code, I think 
public class FooTest { 

    @Test 
    public void testBar_callsBarWithXray() throws Exception { 
     Baz baz = new Baz(); //POJOs 
     Alpha alpha = new Alpha(); 
     alpha.set(new Xray()); 

     Foo foo = new Foo(); 
     Foo stub = spy(foo); // using Mockito, as it's neither final nor "not spyable" 

     // NPE at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.addAnswersForStubbing(PowerMockitoStubberImpl.java:67) 
     PowerMockito.doReturn("ok").when(stub, "bar", Xray.class, Baz.class); 

     stub.bar(alpha, baz); 
     // Testing if bar(Xray, Baz) was called by bar(Alpha, Baz) 
     PowerMockito.verifyPrivate(foo).invoke("bar", Xray.class, Baz.class); 
     // Mockito's equivalent for a public method: verify(stub, times(1)).bar(any(Xray.class), any(Baz.class)); 
    } 
} 

Если я окурок PowerMockito.spy(foo), я получаю IllegalArgumentException: argument type mismatch at org.powermock.reflect.internal.WhiteboxImpl.performMethodInvocation(WhiteboxImpl.java:2014) вместо этого. (Он пузырится вверх по той же линии, что и NPE.)

Я использую Mockito-core 1.9.5, PowerMock 1.5.4 (module-junit4 и api-mockito) и JUnit 4.11.

Что мне нужно изменить, чтобы исключить возможность исключения? Как я могу сделать эту тестовую работу? (Кроме testing that мой класс работает, а не как ... ;-))

ответ

2

При установлении ожиданий мы должны использовать точное совпадение аргументов. В вашем случае это Matchers.any (Xray.class), Matchers.any (Baz.class)

Я изменил ваш код, как показано ниже, а также добавил утверждение assert на выходной объект вашего тестового метода.

@RunWith(PowerMockRunner.class) 
//@PrepareOnlyThisForTest(Foo.class) // we aren't looking at the byte code, I think 
public class FooTest { 

    @Test 
    public void testBar_callsBarWithXray() throws Exception { 
     Baz baz = new Baz(); //POJOs 
     Alpha alpha = new Alpha(); 
     alpha.set(new Xray()); 

     Foo foo = new Foo(); 
     Foo stub = PowerMockito.spy(foo); // using Mockito, as it's neither final nor "not spyable" 

     // NPE at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.addAnswersForStubbing(PowerMockitoStubberImpl.java:67) 
     PowerMockito.doReturn("ok").when(stub, "bar", Matchers.any(Xray.class), Matchers.any(Baz.class)); 

     String res = stub.bar(alpha, baz); 
     Assert.assertEquals("ok", res); 

    //Testing if bar(Xray, Baz) was called by bar(Alpha, Baz) 
    PowerMockito.verifyPrivate(stub).invoke("bar", Matchers.any(Xray.class), Matchers.any(Baz.class)); 
    // Mockito's equivalent for a public method: verify(stub, times(1)).bar(any(Xray.class), any(Baz.class)); 
    } 
} 

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

ДОБАВЛЕНО: Я добавил SYSOUT заявления как в государственных & частных методов «бар», и когда я проверил еще раз, я вижу, что SYSOUT утверждение метода общественного бара не печатается. Это означает, что приведенный выше код издевается над общедоступным методом, но не является частным методом.

Чтобы искусить частный метод «бара», я попытался другим способом издеваться над использованием элемента MemberMatcher.method, который отлично работал.

import org.powermock.api.support.membermodification.MemberMatcher; 

@RunWith(PowerMockRunner.class) 
@PrepareForTest(Foo.class) // we need this 
public class FooTest { 

@Test 
public void testBar_callsBarWithXray() throws Exception { 
    Baz baz = new Baz(); //POJOs 
    Alpha alpha = new Alpha(); 
    alpha.set(new Xray()); 

    Foo stub = PowerMockito.spy(new Foo()); 

    PowerMockito.doReturn("ok") 
     .when(stub, 
       MemberMatcher.method(Foo.class, 
         "bar", 
         Xray.class, Baz.class)) 
     .withArguments(Matchers.any(Xray.class), Matchers.any(Baz.class)); 

    String res = stub.bar(alpha, baz); 

    Assert.assertEquals("ok", res); 

    //Testing if bar(Xray, Baz) was called by bar(Alpha, Baz) 
    PowerMockito.verifyPrivate(stub).invoke("bar", Matchers.any(Xray.class), Matchers.any(Baz.class)); 
    // Mockito's equivalent for a public method: verify(stub, times(1)).bar(any(Xray.class), any(Baz.class)); 
} 

output : public bar 

Метод испытания также передан. Ниже приведены методы foo, имеющие sysouts.

private String bar(Xray xray, Baz baz) { 
    System.out.println("private bar"); 
    return "Xray"; 
} 

public String bar(Alpha alpha, Baz baz) { 

    System.out.println("public bar"); 

    if(alpha.get() instanceof Xray) { 
     return bar((Xray)alpha.get(), baz); 
    } else if(alpha.get() instanceof Zulu) { 
     return bar((Zulu)alpha.get(), baz); 
    } else { 
     return null; 
    } 
} 
+0

Хмм, если я изменю, что в 'PowerMockito.verifyPrivate (тупиковые, раз (5)). Вызова ("бар", Matchers.any (Xray.class), Matchers.any (Baz.class)) ; выясняется, что вы проверяете, как часто вы вызываете 'String res = stub.bar (alpha, baz);' - он, похоже, не смотрит на 'Foo'. Что имеет смысл, так как 'any()' всегда возвращает 'void', насколько я знаю, поэтому PowerMock не имеет возможности проверять типы во время выполнения и соответствует строке bar (Alpha, Baz)'. – Christian

+0

Изменение его на 'Метод m = Whitebox.getMethod (Foo.class, Xray.class, Baz.class);' 'PowerMockito.doReturn (« ok »). Когда (заглушка, m) .withArguments (any (Xray.class), любой (Baz.class)); 'for' times (5) 'просто заставляет его терпеть неудачу с' Wanted, но не вызывается: foo.bar (, ); -> at sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method) На самом деле было нулевое взаимодействие с этим mock.' – Christian

+0

@Christian, мой первый ответ не издевался над методом частного бара, вместо этого он издевался над методом публичных баров, я исправил метод тестирования с помощью MemberMatcher.method, Посмотрите на подробное объяснение в моем обновленном ответе. – kswaughs

Смежные вопросы