英文:
Mock chain call in Mockito causes NullPointerException or WrongTypeOfReturnValue
问题
我正在尝试模拟这个调用:
requestTelemetryContext.getHttpRequestTelemetry().getContext().getOperation()
所以我尝试了以下代码:
OperationContext operationContext = new OperationContext(null);
RequestTelemetryContext requestTelemetryContext = mock(RequestTelemetryContext.class);
when(requestTelemetryContext.getHttpRequestTelemetry().getContext().getOperation()).thenReturn(operationContext); // 导致 java.lang.NullPointerException
但是这给了我一个 java.lang.NullPointerException
。
所以我将其修改为:
OperationContext operationContext = new OperationContext(null);
RequestTelemetryContext requestTelemetryContext = mock(RequestTelemetryContext.class);
RequestTelemetry requestTelemetry = new RequestTelemetry();
when(requestTelemetryContext.getHttpRequestTelemetry()).thenReturn(requestTelemetry);
when(requestTelemetryContext.getHttpRequestTelemetry().getContext().getOperation()).thenReturn(operationContext);
这给了我:
org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
OperationContext 无法由 getHttpRequestTelemetry() 返回
getHttpRequestTelemetry() 应返回 RequestTelemetry
*** 如果您不确定为什么会出现上述错误,请继续阅读。由于上述语法的特性,可能会发生以下问题:
1. 这个异常 *可能* 发生在编写错误的多线程测试中。请参考 Mockito 关于并发测试限制的 FAQ。
2. 使用 when(spy.foo()).then() 语法来存根化 spy。使用 doReturn|Throw() 系列方法来对 spy 进行存根化更安全 -
- 有关 Mockito.spy() 方法的更多信息,请参阅javadoc。
编辑:
我尝试了建议的方法:
OperationContext operationContext = new OperationContext(null);
RequestTelemetryContext requestTelemetryContext = mock(RequestTelemetryContext.class);
RequestTelemetry requestTelemetry = mock(RequestTelemetry.class);
TelemetryContext telemetryContext = mock(TelemetryContext.class);
when(requestTelemetryContext.getHttpRequestTelemetry()).thenReturn(requestTelemetry);
when(requestTelemetry.getContext()).thenReturn(telemetryContext);
when(telemetryContext.getOperation()).thenReturn(operationContext);
ThreadContext.setRequestTelemetryContext(requestTelemetryContext);
不幸的是,这一行 RequestTelemetry requestTelemetry = mock(RequestTelemetry.class);
导致:
Mockito 无法模拟/监视,因为:
- final 类
所以我需要找到一种模拟 final 类的方法。
英文:
I'm trying to mock this call:
requestTelemetryContext.getHttpRequestTelemetry().getContext().getOperation()
So I tried that:
OperationContext operationContext = new OperationContext(null);
RequestTelemetryContext requestTelemetryContext = mock(RequestTelemetryContext.class);
when(requestTelemetryContext.getHttpRequestTelemetry().getContext().getOperation()).thenReturn(operationContext); //causes java.lang.NullPointerException
but that gives me
java.lang.NullPointerException
.
So modified it into:
OperationContext operationContext = new OperationContext(null);
RequestTelemetryContext requestTelemetryContext = mock(RequestTelemetryContext.class);
RequestTelemetry requestTelemetry = new RequestTelemetry();
when(requestTelemetryContext.getHttpRequestTelemetry()).thenReturn(requestTelemetry);
when(requestTelemetryContext.getHttpRequestTelemetry().getContext().getOperation()).thenReturn(operationContext);
that gives me:
> org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
> OperationContext cannot be returned by getHttpRequestTelemetry()
> getHttpRequestTelemetry() should return RequestTelemetry
> *** If you're unsure why you're getting above error read on. Due to the nature of the syntax above problem might occur because:
> 1. This exception might occur in wrongly written multi-threaded tests. Please refer to Mockito FAQ on limitations of concurrency
> testing.
> 2. A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies -
> - with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() method.
I do not understand why it can't just mock the whole chain call and I am not trying to return OperationContext
by getHttpRequestTelemetry
like it states in the error.
EDIT:
I've tried suggested approach:
OperationContext operationContext = new OperationContext(null);
RequestTelemetryContext requestTelemetryContext = mock(RequestTelemetryContext.class);
RequestTelemetry requestTelemetry = mock(RequestTelemetry.class);
TelemetryContext telemetryContext = mock(TelemetryContext.class);
when(requestTelemetryContext.getHttpRequestTelemetry()).thenReturn(requestTelemetry);
when(requestTelemetry.getContext()).thenReturn(telemetryContext);
when(telemetryContext.getOperation()).thenReturn(operationContext);
ThreadContext.setRequestTelemetryContext(requestTelemetryContext);
unfortunately that line RequestTelemetry requestTelemetry = mock(RequestTelemetry.class);
causes:
> Mockito cannot mock/spy because :
> - final class
so i need to find a way to mock final class.
答案1
得分: 2
你需要在调用链的每个阶段返回模拟对象,并且每个模拟对象都应该返回下一个模拟对象,例如:
a().b().c().d()
因此,a()
应该返回一个模拟对象,它被配置为返回模拟对象 b
,依此类推:
when(a()).thenReturn(mockA)
when(mockA.b()).thenReturn(mockB)
等等。
英文:
You need to return the mock at each stage of your call chain, and each mock should return the next mock object e.g.
a().b().c().d()
so a() should return a mock, which is configured to return a mock b etc.
when(a()).thenReturn(mockA);
when(mockA.b()).thenReturn(mockB);
etc.
答案2
得分: 1
你有两个问题。第一个问题涉及到链式操作的模拟 (requestTelemetryContext.getHttpRequestTelemetry().getContext().getOperation()
)。为了解决这个问题而不需要模拟中间的每个类,你可以在模拟时使用 RETURNS_DEEP_STUBS
:
OperationContext operationContext = new OperationContext(null);
RequestTelemetryContext requestTelemetryContext = mock(RequestTelemetryContext.class, RETURNS_DEEP_STUBS);
when(requestTelemetryContext.getHttpRequestTelemetry().getContext().getOperation()).thenReturn(operationContext);
第二个问题是Mockito不能模拟final类 - 恐怕这是无法解决的,你无法模拟一个final类。
英文:
You have two issues here. the first one is with the mock of chained operations (requestTelemetryContext.getHttpRequestTelemetry().getContext().getOperation()
). to solve this without mocking every class in the middle, you can use RETURNS_DEEP_STUBS
when mocking:
OperationContext operationContext = new OperationContext(null);
RequestTelemetryContext requestTelemetryContext = mock(RequestTelemetryContext.class, RETURNS_DEEP_STUBS);
when(requestTelemetryContext.getHttpRequestTelemetry().getContext().getOperation()).thenReturn(operationContext);
The second issue is that mockito cannot mock final classes - this is I'm afraid not solvable, you can't mock a final class
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论