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

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

Null pointer exception when using Mockito to mock interface

问题

  1. 我正在使用Mockito测试以下方法
  2. ```java
  3. protected void produceProducedFieldValue(Target target) throws ValueProducerCreationException {
  4. String mappedValue = (String) valueProducerFactory.createValueProducer("IdProducer", Collections.emptyList()).get();
  5. target.setProducedField(mappedValue);
  6. }

这是我的测试:

  1. @Test
  2. public void TestProducingProducedFieldValue() throws ValueProducerCreationException {
  3. Target mockedTarget = Mockito.mock(Target.class);
  4. ValueProducerFactory valueProducerFactory = Mockito.mock(ValueProducerFactory.class);
  5. List<Object> creationParameters = new ArrayList<>();
  6. String mappedValue = "SomeString";
  7. Mockito.when(valueProducerFactory.createValueProducer("IdProducer", Collections.emptyList()).get()).thenReturn(mappedValue);
  8. SourceToTargetMapper sttm = new SourceToTargetMapper(targetModelObjectFactory, mappingOperatorFactory, mapperFactory, valueProducerFactory);
  9. sttm.produceProducedFieldValue(mockedTarget);
  10. Mockito.verify(mockedTarget, Mockito.times(1)).setProducedField(Mockito.any());
  11. }

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

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

ValueProducerFactory是一个接口

createValueProducer方法的签名如下:

  1. public interface ValueProducerFactory {
  2. <T> Supplier<T> createValueProducer(String producerName, List<Object> creationParameters) throws ValueProducerCreationException;
  3. }

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

  1. @Override
  2. public <T> Supplier<T> createValueProducer(String producerName, List<Object> creationParameters) throws ValueProducerCreationException {
  3. Map<List<Object>, Supplier<?>> parametersToOperatorsMap = producersCache.computeIfAbsent(producerName, s -> new HashMap<>());
  4. List<Object> key = Optional.ofNullable(creationParameters).orElse(Collections.emptyList());
  5. if (!parametersToOperatorsMap.containsKey(key)) {
  6. parametersToOperatorsMap.put(key, nestedProducersFactory.createValueProducer(producerName, creationParameters));
  7. }
  8. return (Supplier<T>) parametersToOperatorsMap.get(key);
  9. }

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

  1. <details>
  2. <summary>英文:</summary>
  3. I&#39;m using Mockito to test the following method:
  4. ```java
  5. protected void produceProducedFieldValue(Target target) throws ValueProducerCreationException {
  6. String mappedValue = (String) valueProducerFactory.createValueProducer(&quot;IdProducer&quot;, Collections.emptyList()).get();
  7. target.setProducedField(mappedValue);
  8. }

Here is my test:

  1. @Test
  2. public void TestProducingProducedFieldValue() throws ValueProducerCreationException {
  3. Target mockedTarget = Mockito.mock(Target.class);
  4. ValueProducerFactory valueProducerFactory = Mockito.mock(ValueProducerFactory.class);
  5. List&lt;Object&gt; creationParameters = new ArrayList&lt;&gt;();
  6. String mappedValue= &quot;SomeString&quot;;
  7. Mockito.when(valueProducerFactory.createValueProducer(&quot;IdProducer&quot;, Collections.emptyList()).get()).thenReturn(mappedValue);
  8. SourceToTargetMapper sttm = new SourceToTargetMapper(targetModelObjectFactory,mappingOperatorFactory,mapperFactory,valueProducerFactory);
  9. sttm.produceProducedFieldValue(mockedTarget);
  10. Mockito.verify(mockedTarget, Mockito.times(1)).setProducedField(Mockito.any());
  11. }

But I keep getting NullPointerExeption for this line:

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

ValueProducerFactory is an Interface

and the createValueProducer method signature is as follows:

  1. public interface ValueProducerFactory {
  2. &lt;T&gt; Supplier&lt;T&gt; createValueProducer(String producerName, List&lt;Object&gt; creationParameters) throws ValueProducerCreationException;
  3. }

I have a class named CachingValueProducerFactory that implements the interface

  1. @Override
  2. public &lt;T&gt; Supplier&lt;T&gt; createValueProducer(String producerName, List&lt;Object&gt; creationParameters) throws ValueProducerCreationException {
  3. Map&lt;List&lt;Object&gt;, Supplier&lt;?&gt;&gt; parametersToOperatorsMap = producersCache.computeIfAbsent(producerName, s -&gt; new HashMap&lt;&gt;());
  4. List&lt;Object&gt; key = Optional.ofNullable(creationParameters).orElse(Collections.emptyList());
  5. if (!parametersToOperatorsMap.containsKey(key)) {
  6. parametersToOperatorsMap.put(key, nestedProducersFactory.createValueProducer(producerName, creationParameters));
  7. }
  8. return (Supplier&lt;T&gt;) parametersToOperatorsMap.get(key);
  9. }

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

答案1

得分: 1

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

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

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

有两种解决方案:

使用深度存根

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

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

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

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

  1. 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:

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

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

  1. Supplier&lt;Object&gt; supplier = () -&gt; mappedValue;
  2. ValueProducerFactory valueProducerFactory = Mockito.mock(ValueProducerFactory.class);
  3. 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:

确定