当您查看堆栈跟踪中列出的类的源代码时(资源包装器), 你发现:
public ResourcesWrapper(Resources resources) {
super(resources.getAssets(), resources.getDisplayMetrics(),
第 46 行是带有 super() 的行。
进一步查看堆栈跟踪中的类,您可能会发现:
private TintContextWrapper(@NonNull final Context base) {
super(base);
...
mResources = new VectorEnabledTintResources(this, base.getResources());
所以,长话短说,是的,你提供了一个non null模拟对象new AppCompatImageView()
在你的代码中。但是你调用的代码正在打电话对此的方法mocked目的。当然,这就是您首先创建模拟的原因。但猜猜怎么了;默认情况下,模拟框架将返回null对于任何方法调用。
换句话说:你必须明白which调用将发生在该模拟上;这样你就可以准备模拟来返回一些东西non null too!
准确地说:我并不是说 TintContextWrapper() 中的那一行代码导致了这个 NPE;我主要是说:当你将一个模拟对象赋予其他代码时,你必须prepare该模拟会在将要发生的方法调用上返回合理的结果。这很可能意味着您必须创建更多模拟;这样就像mockedContext.getResources()
确实返回一个non-null result.
换句话说:你必须
- 识别该模拟对象上发生的那些调用
- 那么你必须确保这些调用将返回非空(例如再次返回模拟对象)。
除此之外:更可能的是,真正的答案是使用安卓专用模拟框架。准备你的模拟让他们“做正确的事”很容易变成大量工作。
Maybe简单的答案是使用深桩来自mockito,只需编写
@Mock (answer = Answers.RETURNS_DEEP_STUBS)
但你需要阅读/尝试;我自己没用过这个。
考虑到你的最新情况:你需要配置你的模拟,就像
when(context.getResources()).thenReturn(someOtherMock);
例如!那就是whole模拟要点:您可以控制调用方法时会发生什么!