2017-02-07 30 views
1

Я пытаюсь проверить метод «reallyCoolMethod», который вызывается с правильными параметрами. Проблема заключается в том, что метод getSillyString вызывает ошибки. Когда метод «getSillyString» является частным, тест проваливается на втором doReturn:Power Mockito Throws «Незавершенная ошибка stubbing», когда метод является закрытым, но не является ошибкой, когда метод защищен

doReturn("superSilly").when(spy, "getSillyString", 5, false);

однако, когда метод защищен, тест будет проходить. Ошибка:

org.mockito.exceptions.misusing.UnfinishedStubbingException: 
Unfinished stubbing detected here: 
-> at org.powermock.api.mockito.internal.PowerMockitoCore.doAnswer(PowerMockitoCore.java:36) 

E.g. thenReturn() may be missing. 
Examples of correct stubbing: 
    when(mock.isOk()).thenReturn(true); 
    when(mock.isOk()).thenThrow(exception); 
    doThrow(exception).when(mock).someVoidMethod(); 
Hints: 
1. missing thenReturn() 
2. you are trying to stub a final method, you naughty developer! 

Вот класс под тестом:

import java.util.Random; 

@Singleton 
public class FooBar { 

    @Inject 
    public FooBar(Foo foo, Bar bar) { 
    this.foo = foo; 
    this.bar = bar; 
    } 

    @POST 
    @Path("foos/") 
    public fooAction createFoo() { 

    word1 = getSillyString(4, true); 
    word2 = getSillyString(5, false); 

    int id = reallyCoolMethod(word1,word2); 
    } 

    private String getSillyString(int size, boolean allCaps){ 
    } 
} 

Вот тест:

import static org.mockito.Mockito.verify; 

import org.junit.Test; 
import org.mockito.Mockito; 

import static org.powermock.api.mockito.PowerMockito.doReturn; 
import static org.powermock.api.mockito.PowerMockito.spy; 

import org.junit.runner.RunWith; 
import org.powermock.api.mockito.PowerMockito; 
import org.powermock.modules.junit4.PowerMockRunner; 

@RunWith(PowerMockRunner.class) 
public class FooTest { 

    @Test 
    public void testCreateFoo() throws Exception { 

     Foo foo = Mockito.mock(Foo.class); 
     Bar bar = Mockito.mock(Bar.class); 
     FooBar resource = new FooBar(foo, bar); 
     FooBar spy = spy(resource); 

     doReturn("reallySilly").when(spy, "getSillyString", 4, true); 
     doReturn("superSilly").when(spy, "getSillyString", 5, false); 

     doReturn(1).when(spy).reallyCoolMethod(Mockito.anyString(),Mockito.anyString()); 
     spy.createFoo(); 
     verify(spy).reallyCoolMethod(Mockito.eq("reallySilly"),Mockito.Eq(superSilly)); 
    } 

} 
+0

Я ничего не знаю о powermockito. Я использую в основном junit и mockito, но это очень странный синтаксис, дающий имя метода как волшебную строку в токене. что происходит, когда 2 класса, которые реализуют один и тот же интерфейс, когда вы издеваетесь над обоими из них, это будет 2 метода, которые, возможно, должны действовать в разных ситуациях. –

+0

Почему вы хотите проверить, был ли вызов 'reallyCoolMethod' в любом случае? Тесты должны быть о внешнем поведении, а не о том, как какой-то результат был достигнут. Я думаю, вам лучше проверить, что возвращаемый 'fooAction' был создан со всеми подходящими свойствами. – Pox

+0

@EbuzerTahaKANAT Это специально из библиотеки PowerMockito, используется для издевательства над частными методами: https://github.com/powermock/powermock/wiki/mockitousage#a-full-example-of-partial-mocking-of-of-parti- a-private-method –

ответ

1

Реальный ответ здесь: вы создали неподходящую для тестирования коды помещая существенный элемент этого класса в частный метод.

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

public interface SillyService { 
    public String getSillyString(); 
} 

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

Желания макет частный метод всегда является следствием плохого дизайна решения. Таким образом, ответ не лежит в Mockito или PowerMock, но, отступая назад, и улучшает этот дизайн.

Для начала можно посмотреть эти videos, чтобы узнать, как написать testable вместо этого.

И кроме этого: обратите внимание, что PowerMock воздействует на вещи, которые вы можете делать с помощью Mockito - поскольку PowerMock поставляется с довольно многообразными версиями Mockito. Моя личная рекомендация: избавиться от вашей потребности в PowerMock; и вместо этого просто используйте последние/самые лучшие версии Mockito.

+0

Спасибо за замечательный ответ! Вероятно, я вернусь к этому решению. Мне просто показалось странным, что издевательство над частным методом работает один раз, но затем выдает ошибку, когда насмехается во второй раз. Его вроде я пропускаю сброс, или мне нужно очистить шпиона. Кроме того, почему изменение метода от частного к защищенному позволяет методу дважды высмеивать? –