空指针异常在使用Mockito模拟接口时发生

huangapple go评论67阅读模式
英文:

Null pointer exception when using Mockito to mock interface

问题

我正在使用Mockito测试以下方法

```java
protected void produceProducedFieldValue(Target target) throws ValueProducerCreationException {
    String mappedValue = (String) valueProducerFactory.createValueProducer("IdProducer", Collections.emptyList()).get();
    target.setProducedField(mappedValue);
}

这是我的测试:

@Test
public void TestProducingProducedFieldValue() throws ValueProducerCreationException {
    Target mockedTarget = Mockito.mock(Target.class);
    ValueProducerFactory valueProducerFactory = Mockito.mock(ValueProducerFactory.class);
    List<Object> creationParameters = new ArrayList<>();

    String mappedValue = "SomeString";

    Mockito.when(valueProducerFactory.createValueProducer("IdProducer", Collections.emptyList()).get()).thenReturn(mappedValue);
    SourceToTargetMapper sttm = new SourceToTargetMapper(targetModelObjectFactory, mappingOperatorFactory, mapperFactory, valueProducerFactory);
    sttm.produceProducedFieldValue(mockedTarget);
    Mockito.verify(mockedTarget, Mockito.times(1)).setProducedField(Mockito.any());
}

但是我一直在这一行中收到NullPointerException

Mockito.when(valueProducerFactory.createValueProducer("IdProducer", Collections.emptyList()).get()).thenReturn(mappedValue);

ValueProducerFactory是一个接口

createValueProducer方法的签名如下:

public interface ValueProducerFactory {

    <T> Supplier<T> createValueProducer(String producerName, List<Object> creationParameters) throws ValueProducerCreationException;

}

我有一个名为CachingValueProducerFactory的类,它实现了这个接口

@Override
public <T> Supplier<T> createValueProducer(String producerName, List<Object> creationParameters) throws ValueProducerCreationException {
    Map<List<Object>, Supplier<?>> parametersToOperatorsMap = producersCache.computeIfAbsent(producerName, s -> new HashMap<>());

    List<Object> key = Optional.ofNullable(creationParameters).orElse(Collections.emptyList());

    if (!parametersToOperatorsMap.containsKey(key)) {
        parametersToOperatorsMap.put(key, nestedProducersFactory.createValueProducer(producerName, creationParameters));
    }

    return (Supplier<T>) parametersToOperatorsMap.get(key);
}

似乎在测试中使用Collections.emptyList()是问题所在,但我没有看到其他解决方案。


<details>
<summary>英文:</summary>

I&#39;m using Mockito to test the following method:

```java
  protected void produceProducedFieldValue(Target target) throws ValueProducerCreationException {
    String mappedValue = (String) valueProducerFactory.createValueProducer(&quot;IdProducer&quot;, Collections.emptyList()).get();
    target.setProducedField(mappedValue);
  }

Here is my test:

     @Test
    public void TestProducingProducedFieldValue() throws ValueProducerCreationException {

        Target mockedTarget = Mockito.mock(Target.class);
        ValueProducerFactory valueProducerFactory = Mockito.mock(ValueProducerFactory.class);
        List&lt;Object&gt; creationParameters = new ArrayList&lt;&gt;();

        String mappedValue= &quot;SomeString&quot;;

        Mockito.when(valueProducerFactory.createValueProducer(&quot;IdProducer&quot;, Collections.emptyList()).get()).thenReturn(mappedValue);
        SourceToTargetMapper sttm = new SourceToTargetMapper(targetModelObjectFactory,mappingOperatorFactory,mapperFactory,valueProducerFactory);
        sttm.produceProducedFieldValue(mockedTarget);
        Mockito.verify(mockedTarget, Mockito.times(1)).setProducedField(Mockito.any());
    }

But I keep getting NullPointerExeption for this line:

    Mockito.when(valueProducerFactory.createValueProducer(&quot;IdProducer&quot;, Collections.emptyList()).get()).thenReturn(mappedValue);

ValueProducerFactory is an Interface

and the createValueProducer method signature is as follows:

    public interface ValueProducerFactory {

        &lt;T&gt; Supplier&lt;T&gt; createValueProducer(String producerName, List&lt;Object&gt; creationParameters) throws ValueProducerCreationException;

    }

I have a class named CachingValueProducerFactory that implements the interface

    @Override
    public &lt;T&gt; Supplier&lt;T&gt; createValueProducer(String producerName, List&lt;Object&gt; creationParameters) throws ValueProducerCreationException {
        Map&lt;List&lt;Object&gt;, Supplier&lt;?&gt;&gt; parametersToOperatorsMap = producersCache.computeIfAbsent(producerName, s -&gt; new HashMap&lt;&gt;());

        List&lt;Object&gt; key = Optional.ofNullable(creationParameters).orElse(Collections.emptyList());

        if (!parametersToOperatorsMap.containsKey(key)) {
            parametersToOperatorsMap.put(key, nestedProducersFactory.createValueProducer(producerName, creationParameters));
        }

        return (Supplier&lt;T&gt;) parametersToOperatorsMap.get(key);
    }

It seems like using Collections.emptyList() in the test is the problem, but I don't see any other solution for this.

答案1

得分: 1

你正在尝试同时模拟两个方法。在这一行中:

Mockito.when(valueProducerFactory.createValueProducer("IdProducer", Collections.emptyList()).get()).thenReturn(mappedValue);

你正在调用createValueProducer()调用的结果上的get()方法,因为你还没有模拟它,所以它是null

有两种解决方案:

使用深度存根

ValueProducerFactory valueProducerFactory = Mockito.mock(ValueProducerFactory.class, Mockito.RETURNS_DEEP_STUBS);
Mockito.when(valueProducerFactory.createValueProducer("IdProducer", Collections.emptyList()).get()).thenReturn(mappedValue);

首先模拟Supplier(注意已删除的get()):

Supplier<Object> supplier = () -> mappedValue;
ValueProducerFactory valueProducerFactory = Mockito.mock(ValueProducerFactory.class);
Mockito.when(valueProducerFactory.createValueProducer("IdProducer", Collections.emptyList())).thenReturn(supplier);
英文:

You are trying to mock two methods at once. In this line:

Mockito.when(valueProducerFactory.createValueProducer(&quot;IdProducer&quot;, Collections.emptyList()).get()).thenReturn(mappedValue);

you are calling get() on the result of the createValueProducer() call, which is null because you haven't mocked it yet.

There are two solutions:

Use deep stubbing:

ValueProducerFactory valueProducerFactory = Mockito.mock(ValueProducerFactory.class, Mockito.RETURNS_DEEP_STUBS);
Mockito.when(valueProducerFactory.createValueProducer(&quot;IdProducer&quot;, Collections.emptyList()).get()).thenReturn(mappedValue);

Mock the Supplier first (pay attention to the removed get()):

Supplier&lt;Object&gt; supplier = () -&gt; mappedValue;
ValueProducerFactory valueProducerFactory = Mockito.mock(ValueProducerFactory.class);
Mockito.when(valueProducerFactory.createValueProducer(&quot;IdProducer&quot;, Collections.emptyList())).thenReturn(supplier);

huangapple
  • 本文由 发表于 2020年10月17日 04:44:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/64396179.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定