【问题标题】:Nullpointer Exception for mocking final method用于模拟最终方法的 Nullpointer 异常
【发布时间】:2019-10-11 04:29:22
【问题描述】:

尝试模拟时得到 NullPointerException Aggregations.getAsMap()

我已经尝试过使用 PowerMockito.doReturn(map).when(aggs).getAsMap() 的其他不同方法,但仍然面临同样的问题

@PrepareForTest(Aggregations.class)
public class TestExample extends PowerMockTestCase {

    @Test
    public void testMyMethod() {
        Aggregations aggs = PowerMockito.mock(Aggregations.class);
        Cardinality cardinality = Mockito.mock(Cardinality.class);
        Map<String, Aggregation> map = new HashMap<String, Aggregation>();
        map.put("sample", cardinality);
        Mockito.when(aggs.getAsMap()).thenReturn(map);
    }

}
Mockito.when(aggs.getAsMap()).thenReturn(map);

当调试 aggs 值包含以下值时

{Aggregations$MockitoMock$485838759@3084} Method threw 'java.lang.NullPointerException' exception. Cannot evaluate org.elasticsearch.search.aggregations.Aggregations$MockitoMock$485838759.toString()

使用 testng 及以下版本的 jars

powermock-api-mockito-2.0.2.jar

mockito-core-2.23.0.jar

【问题讨论】:

  • 试试PowerMockito.when(aggs.getAsMap()).thenReturn(map);。 Mockito 似乎无法模拟 final 方法。

标签: java elasticsearch mockito testng powermockito


【解决方案1】:

您收到异常是因为“getAsMap”是最终方法,并且 mockito 进行了实际的 API 调用而不是模拟调用。这是因为 Mockito 默认不支持模拟 final 方法和类。

解决方案:您需要包含一个 mockito-extension 插件来支持此功能,而且非常简单。

查看https://www.baeldung.com/mockito-final 了解步骤。

【讨论】:

    【解决方案2】:

    NullPointerException 来自getAsMap 方法的调用。

    使用Mockito.doReturn(map).when(aggs).getAsMap(); 应该可以解决该问题。

    但是PowerMockito 中似乎存在一个错误,因为这样编写它不应该触发getAsMap() 方法的调用(仍然会发生)。

    我建议你在他们的bugtracker 中为这个问题创建一个错误票。


    如果您为Mockito(参见here)启用最终模拟,则运行测试成功。

    @RunWith(MockitoJUnitRunner.class)
    public class TestExample {
    
        @Test
        public void testMyMethod() {
            Aggregations aggs = Mockito.mock(Aggregations.class);
            Cardinality cardinality = Mockito.mock(Cardinality.class);
            Map<String, Aggregation> map = new HashMap<String, Aggregation>();
            map.put("sample", cardinality);
    
            Mockito.doReturn(map).when(aggs).getAsMap();
            Assert.assertEquals(map, aggs.getAsMap());
        }
    }
    

    另一种选择可能是使用真正的Aggregations 对象:

    @Test
    public void testMyMethod() {
    
        Cardinality cardinality = Mockito.mock(Cardinality.class);
        Mockito.when(cardinality.getName()).thenReturn("sample");
    
        List<Aggregation> list = new ArrayList<>();
        list.add(cardinality);
    
        Aggregations aggs = new Aggregations(list);
        Map<String, Aggregation> map = aggs.getAsMap();
    
        Assert.assertEquals(1, map.size());
        Assert.assertEquals(cardinality, map.get("sample"));
    }  
    

    【讨论】:

    • 谢谢,我采用了第二种创建真实对象的方法,它奏效了。将在错误跟踪器中提出问题
    • @Developer ,如果上述答案对您有用,您应该接受它作为正确答案。
    • @Developer:你添加了 bugticket 吗?如果是这样,您可以将链接添加为评论吗?
    猜你喜欢
    • 2016-04-18
    • 1970-01-01
    • 1970-01-01
    • 2011-04-17
    • 2018-01-01
    • 1970-01-01
    • 2017-09-23
    相关资源
    最近更新 更多