0

Это теперь часть 3 в series ...PowerMockito не соответствует перегруженный метод, когда возвращаемые типы отличаются

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

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

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

    public void bar(Alpha alpha, Baz baz) { // this one returns nothing 
     if(alpha.get() instanceof Xray) { 
      System.out.println(bar((Xray) alpha.get(), baz)); 
      return; 
     } else if(alpha.get() instanceof Zulu) { 
      System.out.println(bar((Zulu)alpha.get(), baz)); 
      return; 
     } else { 
      return; 
     } 
    } 
} 

Пользователь kswaughs solved the issue для частные перегруженные методы, когда все методы имеют одинаковый тип возврата. И elsewhere было предложено использовать метод when() с Method объекта ... Тем не менее, теперь, когда я определил bar(Alpha, Baz) использовать другой тип возвращаемого образуют другие методы, все разваливается снова:

@RunWith(PowerMockRunner.class) 
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); 

     Method m = Whitebox.getMethod(Foo.class, "bar", Xray.class, Baz.class); 

     PowerMockito.doReturn("ok").when(stub, m); 

     stub.bar(alpha, baz); // fails here - even though that then calls stub.bar(Xray, Baz); 

     // Testing if bar(Xray, Baz) was called by bar(Alpha, Baz) 
     PowerMockito.verifyPrivate(stub, times(5)).invoke("bar", any(Xray.class), any(Baz.class)); 
    } 
} 

Исключение во всей своей красе:

org.mockito.exceptions.base.MockitoException: 
'bar' is a *void method* and it *cannot* be stubbed with a *return value*! 
Voids are usually stubbed with Throwables: 
    doThrow(exception).when(mock).someVoidMethod(); 
*** 
If you're unsure why you're getting above error read on. 
Due to the nature of the syntax above problem might occur because: 
1. The method you are trying to stub is *overloaded*. Make sure you are calling the right overloaded version. 
2. Somewhere in your test you are stubbing *final methods*. Sorry, Mockito does not verify/stub final methods. 
3. A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies - 
    - with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() method. 

    at FooTest.testBar_callsBarWithXray(FooTest.java:31) 

Использование .withArguments(any(Xray.class), any(Baz.class)) не кажется, чтобы сделать разницу.

В то время как пятно, исключение, к сожалению, не говорит о том, как сделать точку 1 осуществленной с настройкой, которую у меня есть. Есть идеи?

+0

Я думаю, что вы пропускаете анонимность типа класса @PrepareForTest (Foo.class) –

ответ

0

Здесь проблема не с разными типами возвращаемых данных, это только с перегруженными методами. Используйте MemberMatcher.method() вместо WhiteBox.getMethod, Для целей тестирования добавлен оператор sysout в верхней части метода публичных баров.

public void bar(Alpha alpha, Baz baz) { // this one returns nothing 

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

if(alpha.get() instanceof Xray) { 
    System.out.println(bar((Xray) alpha.get(), baz)); 
    return; 
} else if(alpha.get() instanceof Zulu) { 
    System.out.println(bar((Zulu)alpha.get(), baz)); 
    return; 
} else { 
    return; 
} 
} 

Ниже приведен метод испытания, PrepareForTest требуется для Foo.class, когда мы используем MemberMatcher.

@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()); 

    Method m = MemberMatcher.method(Foo.class, 
       "bar", 
       Xray.class, Baz.class); 

    PowerMockito.doReturn("ok") 
     .when(stub, m) 
     .withArguments(Matchers.any(Xray.class), Matchers.any(Baz.class)); 

    stub.bar(alpha, baz); 

    PowerMockito.verifyPrivate(stub, Mockito.times(1)).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 is : 
public bar 
ok