单元测试失败(JUnit + Mockito)-空指针异常

时间:2018-11-05 20:14:40

标签: unit-testing nullpointerexception mockito

我是新来的,所以我希望为您提供帮助我的所有信息。 我正在尝试编写一个单元测试(Junit + Mockito),在此特定方法上检查其他问题,但均未成功

    public void saveRequest(final HttpServletRequest request, final HttpServletResponse response)
{
    //this might be called while in ExceptionTranslationFilter#handleSpringSecurityException in this case base implementation
    if (getSecurityContext().getAuthentication() == null)
    {
        callSuperSaveRequest(request, response);
    }
    else
    {
        final SavedRequest savedBefore = getRequest(request, response);
        if (savedBefore != null)//to not override request saved by ExceptionTranslationFilter#handleSpringSecurityException
        {
            return;
        }

        if (getRequestMatcher().matches(request))
        {
            final DefaultSavedRequest savedRequest = new DefaultSavedRequest(request, getPortResolver())
            {
                private final String referer = request.getHeader(REFERER);

                @Override
                public String getRedirectUrl() { return referer; }
            };

            if (isCreateSessionAllowed() || request.getSession(false) != null)
            {
                request.getSession().setAttribute(SAVED_REQUEST, savedRequest);
                logger.debug("DefaultSavedRequest added to Session: " + savedRequest);
            }
        }
        else
        {
            logger.debug("Request not saved as configured RequestMatcher did not match");
        }
    }
}

这是我到目前为止编写的单元测试

@Test
public void testSaveRequestIfSavedBeforeIsNull()
{
    given(request.getRequestURL()).willReturn(new StringBuffer("dummy"));
    given(request.getScheme()).willReturn("dummy");
    given(request.getHeader("referer")).willReturn("some blah");
    given(portResolver.getServerPort(request)).willReturn(100);
    doReturn(portResolver).when(cache).getPortResolver();
    defaultSavedRequest = new DefaultSavedRequest(request, portResolver);
    doReturn(true).when(cache.isCreateSessionAllowed());
    given(request.getSession()).willReturn(httpSession);

    cache.saveRequest(request, response);

    verify(request.getSession()).setAttribute(Matchers.eq("SPRING_SECURITY_SAVED_REQUEST"),
            Mockito.argThat(new DefaultSavedRequestArgumentMatcher("some blah")));
}

模拟/注入以下实例

    @Spy
@InjectMocks
private WebHttpSessionRequestCache cache;

@Mock
private HttpServletRequest request;

@Mock
private HttpServletResponse response;

@Mock
private SecurityContext securityContext;

@Mock
private PortResolver portResolver;

@Mock
private SavedRequest savedBefore;

@Mock
private Authentication authentication;

@Mock
private DefaultSavedRequest defaultSavedRequest;

@Mock
private HttpSession httpSession;

但这是我的错误

java.lang.NullPointerException
at org.springframework.security.web.savedrequest.DefaultSavedRequest.<init>(DefaultSavedRequest.java:91)
at com.superdrug.storefront.security.impl.WebHttpSessionRequestCacheUnitTest.testSaveRequestIfSavedBeforeIsNull(WebHttpSessionRequestCacheUnitTest.java:116)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.CommandLineWrapper.main(CommandLineWrapper.java:67)

如果我没记错,我认为该错误是由另一个类“ DefaultSavedRequest”引起的;我试图嘲笑它,但某些方法不起作用...

这是“ DefaultSavedRequest”类

public class DefaultSavedRequest implements SavedRequest {
protected static final Log logger = LogFactory.getLog(DefaultSavedRequest.class);
private static final String HEADER_IF_NONE_MATCH = "If-None-Match";
private static final String HEADER_IF_MODIFIED_SINCE = "If-Modified-Since";
private final ArrayList<SavedCookie> cookies = new ArrayList();
private final ArrayList<Locale> locales = new ArrayList();
private final Map<String, List<String>> headers;
private final Map<String, String[]> parameters;
private final String contextPath;
private final String method;
private final String pathInfo;
private final String queryString;
private final String requestURI;
private final String requestURL;
private final String scheme;
private final String serverName;
private final String servletPath;
private final int serverPort;

public DefaultSavedRequest(HttpServletRequest request, PortResolver portResolver) {
    this.headers = new TreeMap(String.CASE_INSENSITIVE_ORDER);
    this.parameters = new TreeMap(String.CASE_INSENSITIVE_ORDER);
    Assert.notNull(request, "Request required");
    Assert.notNull(portResolver, "PortResolver required");
    Cookie[] cookies = request.getCookies();
    if (cookies != null) {
        Cookie[] arr$ = cookies;
        int len$ = cookies.length;

        for(int i$ = 0; i$ < len$; ++i$) {
            Cookie cookie = arr$[i$];
            this.addCookie(cookie);
        }
    }

    Enumeration names = request.getHeaderNames();

    while(true) {
        String name;
        do {
            do {
                if (!names.hasMoreElements()) {
                    Enumeration locales = request.getLocales();

                    while(locales.hasMoreElements()) {
                        Locale locale = (Locale)locales.nextElement();
                        this.addLocale(locale);
                    }

                    Map<String, String[]> parameters = request.getParameterMap();
                    Iterator i$ = parameters.keySet().iterator();

                    while(i$.hasNext()) {
                        String paramName = (String)i$.next();
                        Object paramValues = parameters.get(paramName);
                        if (paramValues instanceof String[]) {
                            this.addParameter(paramName, (String[])((String[])paramValues));
                        } else if (logger.isWarnEnabled()) {
                            logger.warn("ServletRequest.getParameterMap() returned non-String array");
                        }
                    }

                    this.method = request.getMethod();
                    this.pathInfo = request.getPathInfo();
                    this.queryString = request.getQueryString();
                    this.requestURI = request.getRequestURI();
                    this.serverPort = portResolver.getServerPort(request);
                    this.requestURL = request.getRequestURL().toString();
                    this.scheme = request.getScheme();
                    this.serverName = request.getServerName();
                    this.contextPath = request.getContextPath();
                    this.servletPath = request.getServletPath();
                    return;
                }

                name = (String)names.nextElement();
            } while("If-Modified-Since".equalsIgnoreCase(name));
        } while("If-None-Match".equalsIgnoreCase(name));

        Enumeration values = request.getHeaders(name);

        while(values.hasMoreElements()) {
            this.addHeader(name, (String)values.nextElement());
        }
    }
}

那么我想念的是什么?

1 个答案:

答案 0 :(得分:0)

我认为执行以下行时会引发错误:

    defaultSavedRequest = new DefaultSavedRequest(request, portResolver);

您模拟了var defaultSavedRequest,但随后尝试使用实际方法对其进行初始化,但这对于模拟对象是不可能的。模拟对象就像一个空对象,但是具有与创建它的类相同的方法名称。要使用类中的原始方法,您必须使用“间谍”而不是“模拟”,例如:

private DefaultSavedRequest defaultSavedRequest = spy(new DefaultSavedRequest(request, portResolver));

然后,您可以在Spy-Object中设置和替换方法,但是所有未被测试覆盖的方法均保留其原始内容。