Mockito模拟HttpHeaders移除setUp()触发空指针异常求解
嘿,我明白你的困扰——刚接触Mockito,本来想简单模拟个HttpHeaders,结果移除setUp()就报NPE,还要写一堆繁琐的子类实现,确实头疼。让我帮你搞定这个问题!
问题根源分析
首先得搞清楚为什么移除setUp()会报错:你用了@Mock注解标注HttpHeaders headers,Mockito会给你生成一个mock对象,但这个mock对象的所有方法默认返回null。之前你的setUp()里手动new了一个HttpHeaders的子类,手动实现了getRequestHeaders()等方法返回非null的对象(比如MultivaluedHashMap),所以调用headers.getRequestHeaders().putSingle()不会出问题;但移除setUp后,mock的getRequestHeaders()返回null,再调用putSingle自然就触发NullPointerException了。
方案一:简洁版setUp配置(适合多测试方法复用)
不用再写一堆子类覆盖方法,只用几行代码配置mock的行为就行。如果多个测试方法都需要用到这个HttpHeaders的配置,用@Before做统一初始化最方便:
@RunWith(SpringJUnit4ClassRunner.class) public class ValidateAndQuotetValidatorTest { @InjectMocks private ValidateAndQuotetValidator validator; @Mock private HttpHeaders headers; @Before public void setUp() throws Exception { // 初始化Mockito(确保@Mock注解生效) MockitoAnnotations.initMocks(this); // 配置getRequestHeaders返回一个空的MultivaluedHashMap,避免null MultivaluedMap<String, String> mockRequestHeaders = new MultivaluedHashMap<>(); Mockito.when(headers.getRequestHeaders()).thenReturn(mockRequestHeaders); // 如果你的测试还用到其他方法,比如getRequestHeader,也可以按需配置 Mockito.when(headers.getRequestHeader(Mockito.anyString())).thenReturn(new ArrayList<>()); } @Test(expected = ServiceException.class) public void test_validateRequest_12() throws Exception { headers.getRequestHeaders().putSingle(ExternalPartnerUtil.PARTNER_NAME, ""); headers.getRequestHeaders().putSingle(ExternalPartnerUtil.AGENT_ID, "asd"); validator.validateHeaders(headers); } }
这样setUp的代码非常简洁,完全替代了之前繁琐的子类实现。
方案二:无setUp,直接在测试方法内配置
如果只有这一个测试方法需要用到这个HttpHeaders,也可以去掉@Before,直接在测试方法里配置mock行为:
@RunWith(SpringJUnit4ClassRunner.class) public class ValidateAndQuotetValidatorTest { @InjectMocks private ValidateAndQuotetValidator validator; @Mock private HttpHeaders headers; @Test(expected = ServiceException.class) public void test_validateRequest_12() throws Exception { // 初始化Mockito(如果SpringJUnit4ClassRunner没自动处理的话) MockitoAnnotations.initMocks(this); // 配置getRequestHeaders返回非null的Map MultivaluedMap<String, String> mockRequestHeaders = new MultivaluedHashMap<>(); Mockito.when(headers.getRequestHeaders()).thenReturn(mockRequestHeaders); // 直接操作这个Map,不用通过headers.getRequestHeaders()链式调用(更安全) mockRequestHeaders.putSingle(ExternalPartnerUtil.PARTNER_NAME, ""); mockRequestHeaders.putSingle(ExternalPartnerUtil.AGENT_ID, "asd"); validator.validateHeaders(headers); } }
这里直接操作我们创建的mockRequestHeaders,比链式调用更不容易出错,也更清晰。
额外小提示
如果你不需要Spring的上下文支持,还可以把@RunWith(SpringJUnit4ClassRunner.class)换成@RunWith(MockitoJUnitRunner.class),这样Mockito会自动初始化@Mock的对象,连MockitoAnnotations.initMocks(this)都可以省去。
内容的提问来源于stack exchange,提问作者Krish

