【问题标题】:JUnit and Mockito Null Pointer Exception [duplicate]JUnit 和 Mockito 空指针异常 [重复]
【发布时间】:2016-08-19 07:12:33
【问题描述】:

我有一个名为 Pinger Service 的类,它调用 HttpAdapter 打开 HttpURLConnection 并返回它,然后调用 getResponseCode 来确定 URL 是否为 200。

我正在尝试模拟 HttpURLConnection 并使 getResponseCode 返回 404,但是我得到了一个空指针异常

测试

package com.uk.jacob.service;

import static org.junit.Assert.*;

import java.io.IOException;
import java.net.HttpURLConnection;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;

import com.uk.jacob.SimplePingApplication;
import com.uk.jacob.adapter.HttpAdapter;
import com.uk.jacob.model.Website;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SimplePingApplication.class)
@WebAppConfiguration
public class PingerServiceTests {

    @Autowired
    PingerService pingerService;

    @Mock
    HttpAdapter httpAdapter;

    @Mock
    HttpURLConnection mockHttpURLConnection;

    @Test
    public void testPingerServiceReturnsOkWhenServiceIsUp() throws IOException{
        Website website = pingerService.ping("http://devnews.today");

        assertEquals(true, website.ok);
    }

    @Test
    public void testPingerServiceReturnsOkWhenServiceIsNotFound() throws IOException{
        Mockito.when(mockHttpURLConnection.getResponseCode()).thenReturn(404);
        Mockito.when(httpAdapter.createHttpURLConnection("http://devnews.today")).thenReturn(mockHttpURLConnection);

        Website website = pingerService.ping("http://devnews.today");

        assertEquals(false, website.ok);
    }

    @Test
    public void testPingerServiceReturnsOkWhenServiceIsDown(){
        Website website = pingerService.ping("https://jacob.uk.comz");

        assertEquals(false, website.ok);
    }

}

Pinger 服务

package com.uk.jacob.service;

import java.net.HttpURLConnection;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.uk.jacob.adapter.HttpAdapter;
import com.uk.jacob.model.Website;

@Component
public class PingerService {

    @Autowired
    HttpAdapter httpAdapter;

    @Autowired
    Website website;

    public Website ping(String urlToPing) {     
        try {
            HttpURLConnection connection = httpAdapter.createHttpURLConnection(urlToPing);

            System.out.println(connection.getResponseCode());

            if(connection.getResponseCode() == 200){
                website.ok = true;
            }
        } catch (Exception e) {
            website.ok = false;
        }

        return website;
    }
}

HttpAdapter

package com.uk.jacob.adapter;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;

import org.springframework.stereotype.Component;

@Component
public class HttpAdapter {
    public HttpURLConnection createHttpURLConnection(String urlToPing) throws IOException{
        URL url = new URL(urlToPing);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();

        connection.setRequestMethod("GET");
        connection.connect();

        return connection;
    }
}

故障跟踪

java.lang.NullPointerException
    at com.uk.jacob.service.PingerServiceTests.testPingerServiceReturnsOkWhenServiceIsNotFound(PingerServiceTests.java:44)
    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:483)
    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.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:254)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89)
    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.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:193)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

【问题讨论】:

  • 请提供堆栈跟踪
  • @ManoDestra 不,怎么样?这显然与 Mockito 和我的 spring bean 没有正确注入有关。
  • 您的测试做出了很大的假设,即它们具有从前一次调用返回的每个对象(非空)。检查每个返回的对象以查看哪个为空是一件简单的事情。堆栈跟踪会准确地告诉您它发生的位置:PingerServiceTests.java:44
  • 看看这个例子中的测试类,我认为你不应该在测试类中使用 Autowired 注解。您应该改用@InjectMocks。 stackoverflow.com/questions/36167148/…

标签: java spring junit spring-boot


【解决方案1】:

您使用SpringJUnit4ClassRunneras far as I know 运行测试,除非您使用MockitoJunitRunnerMockitoAnnotations.initMocks(this);,否则@Mock 不起作用。

另请注意,您的代码中没有没有可以让您的服务使用您的模拟。

这就是您获得 NPE 的原因,因为 mockHttpURLConnection 在您的测试方法中为空。

【讨论】:

  • 添加 MockitoAnnotations.initMocks(this);工作,我的测试似乎正在使用我的模拟,我将如何明确告诉我的服务使用我的模拟?服务上的@InjectMocks 注释?
  • 不确定@InjectMock,一个好的老二传手会做这项工作
  • 是的,@InjectMocks 的目的与使用所有 Mock 对象的目的完全相同
  • 那这个答案不应该标记为正确吗?
【解决方案2】:

您用于存根从 HttpAdapter 创建的 HttpUrlConnection 的 url 值,即对 httpAdapter.createHttpURLConnection 的调用与您传递给 pingerService.ping 的值不匹配。 devnews.today != http://devnews.today

检查这两行

Mockito.when(httpAdapter.createHttpURLConnection("devnews.today")).thenReturn(mockHttpURLConnection);

网站网站 = pingerService.ping("http://devnews.today");

因此在运行时 HttpUrlConnection 实际上是 null 并且模拟的默认返回值

【讨论】:

  • 更新了例子,即使有了这个集合,它仍然返回null。
【解决方案3】:
Try this and change @Autowired to @InjectMocks in test class.


        @Test
        public void testPingerServiceReturnsOkWhenServiceIsNotFound() throws IOException{  
    Mockito.when(httpAdapter.createHttpURLConnection("http://devnews.today")).thenReturn(mockHttpURLConnection);

    Mockito.when(mockHttpURLConnection.getResponseCode()).thenReturn(404);

            Website website = pingerService.ping("http://devnews.today");

            assertEquals(false, website.ok);
        }

【讨论】:

    【解决方案4】:

    PingerService 上使用@InjectMocks 代替@Autowire

    然后,(因为您使用的是SpringJUnit4ClassRunner.class)添加一个带有@Before 注释的方法。在那个方法里面写MockitoAnnotations.initMocks(this)

    如果不想使用MockitoAnnotations.initMocks(this),可以使用MockitoJunitRunner

    import com.uk.jacob.SimplePingApplication;
    import com.uk.jacob.adapter.HttpAdapter;
    import com.uk.jacob.model.Website;
    import org.mockito.InjectMocks;
    import org.mockito.MockitoAnnotations;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = SimplePingApplication.class)
    @WebAppConfiguration
    public class PingerServiceTests {
    
        @InjectMocks
        PingerService pingerService;
    
        @Mock
        HttpAdapter httpAdapter;
    
        @Mock
        HttpURLConnection mockHttpURLConnection;
    
    
        @Before
        public void setUp() {
            MockitoAnnotations.initMocks(this);
        }    
    
        @Test
        public void testPingerServiceReturnsOkWhenServiceIsUp() throws IOException{
            Website website = pingerService.ping("http://devnews.today");
    
            assertEquals(true, website.ok);
        }
    
        @Test
        public void testPingerServiceReturnsOkWhenServiceIsNotFound() throws IOException{
            Mockito.when(mockHttpURLConnection.getResponseCode()).thenReturn(404);
            Mockito.when(httpAdapter.createHttpURLConnection("http://devnews.today")).thenReturn(mockHttpURLConnection);
    
            Website website = pingerService.ping("http://devnews.today");
    
            assertEquals(false, website.ok);
        }
    
        @Test
        public void testPingerServiceReturnsOkWhenServiceIsDown(){
            Website website = pingerService.ping("https://jacob.uk.comz");
    
            assertEquals(false, website.ok);
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-24
      • 2021-06-15
      • 2021-06-30
      • 1970-01-01
      • 2015-10-07
      • 1970-01-01
      • 2019-04-09
      • 1970-01-01
      相关资源
      最近更新 更多