Mockito / PowerMockito:奇怪的Stubbing Exception

时间:2015-10-30 17:17:54

标签: java mockito powermockito

我收到此org.mockito.exceptions.misusing.UnfinishedStubbingException,但根据我在互联网上找到的所有帖子和说明,它似乎没有意义。

异常方法声明thenReturn可能会丢失,但事实并非如此。我在下面的示例代码中专门留下了两个方面:doReturnthenReturn。他们都没有工作。两者都有相同的异常消息。

此外,没有内联模拟。我准备了所有静态类,并且正在使用PowerMockitoRunner。

我找不到任何出路。任何人都可以帮我找出发生了什么?

编辑:我忘了提到我正在使用Mockito 1.8.5和PowerMockito 1.4.10。

完全例外:

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

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. although stubbed methods may return mocks, you cannot inline mock creation (mock()) call inside a thenReturn method (see issue 53)

    at br.com.tests.email.EnvioCompartilhamento.mockCaptcha(EnvioCompartilhamento.java:120)
    at br.com.tests.email.EnvioCompartilhamento.setup(EnvioCompartilhamento.java:60)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at org.junit.internal.runners.MethodRoadie.runBefores(MethodRoadie.java:132)
    at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:95)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:294)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:282)
    at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:86)
    at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:207)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:146)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:120)
    at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:33)
    at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:45)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:118)
    at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:102)
    at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

我的考试班。代码行添加了10乘10(或类型):

006 --> import br.com.common.MyProperties;
import br.com.struts.email.EnvioDeEmail;
import br.com.struts.email.forms.FormularioParaCompartilhamento;
import br.com.util.UrlUtil;
010 --> import br.com.popular.commons.Publications;
import br.com.popular.commons.utils.escenic.RetrievingObjects;
import com.captcha.Captcha;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
020 --> import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;

import static org.junit.Assert.assertNull;
030 --> import static org.junit.Assert.fail;
import static org.mockito.Matchers.*;
import static org.powermock.api.mockito.PowerMockito.*;

040 --> @RunWith(PowerMockRunner.class)
@PrepareForTest({ Captcha.class, RetrievingObjects.class, UrlUtil.class })
public class EnvioCompartilhamento {

    @Mock
    private ActionMapping mapping;

    @Mock
    private HttpServletRequest request;

050 --> @Mock
    private HttpServletResponse response;

    private FormularioParaCompartilhamento formulario;

    @Before
    public void setup() throws NoSuchMethodException, NoSuchFieldException, IOException {

        mockStaticClasses();
        mockRequestBehavior();
    060 --> mockCaptcha();
        mockResponse();
        formulario = new FormularioParaCompartilhamento();
    }

    @Test
    public void compartilhamentoComSucesso() {

        formulario.setEmailTo("teste@teste.com");
        formulario.setIdArtigo("12345");
    070 --> formulario.setIsArtigo(true);
        formulario.setMessage("Corpo do email");
        formulario.setTitulo("Titulo");
        formulario.setUrl("http://www.google.com");
        formulario.setCaptcha("ABCD");

        EnvioDeEmail email = new EnvioDeEmail();
        final ActionForward resultado = email.compartilhamento(mapping, formulario, request, response);

        assertNull(resultado);
    080 --> }

    112 --> private void mockRequestBehavior() {

        when(request.getMethod()).thenReturn("POST");
        when(request.getHeader("X-FORWARDED-FOR")).thenReturn("User IP");
    }

    private void mockCaptcha() {

    120 --> HttpSession session = mock(HttpSession.class);
        doReturn(session).when(request).getSession();
        Captcha captcha = Mockito.mock(Captcha.class);
        doReturn(captcha).when(session).getAttribute("captcha");
        doReturn(true).when(captcha).isInputValid(anyString());
    }

    private void mockStaticClasses() {

        final MyProperties myProperties = mock(MyProperties.class);
    130 --> mockStatic(RetrievingObjects.class);
        when(RetrievingObjects.componentFromPublicationAtSystemScope(any(Publications.class), eq("EmailProperties"), eq(MyProperties.class))).
            thenReturn(myProperties);
        mockStatic(UrlUtil.class);
        doNothing().when(UrlUtil.class);
    }

    private void mockResponse() throws IOException {

        PrintWriter writer = mock(PrintWriter.class);
    140 --> doReturn(writer).when(response).getWriter();
    }

}

1 个答案:

答案 0 :(得分:1)

doNothing().when(UrlUtil.class);

这对Mockito或PowerMock来说并不意味着什么;您需要指定要模拟的特定呼叫。这使得这个存根未完成。请参阅PowerMockito when docs作为示例。

但是,Mockito 无法在此行告知您的存根未完成 - 它只会在您与其进行交互时引发错误,因此它只会在稍后检测到错误情况,你的mockCaptcha方法。

要解决此问题,请按以下步骤完成UrlUtil存根(我指定PowerMockito以区别于Mockito.doNothing,尽管看起来您的静态导入正确):

PowerMockito.doNothing().when(UrlUtil.class);
UrlUtil.methodYouWantToMock();

或者,要使UrlUtil默认禁止其所有行为,请删除doNothing行和put a default answer into your mockStatic call

mockStatic(UrlUtil.class, RETURNS_SMART_NULLS);