java - 获取 Mockito 错误:“需要但未调用...实际上,与此模拟的交互为零”
问题描述
我在 Android 项目(在 Android Studio 中)中为 java 类运行单元测试时遇到上述错误。
被测类:
import android.content.Context;
import android.util.Log;
import **.CustomObject;
import java.util.concurrent.CountDownLatch;
import androidx.annotation.NonNull;
public class CustomClass {
private static final String string = "a";
private static CustomObject customObject = null;
private static CountDownLatch initializedLatch = new CountDownLatch(1);
@NonNull
public static CustomObject1 getCustomObject1() {
try {
initializedLatch.await();
assert customObject != null;
return customObject;
} catch (InterruptedException e) {
throw new RuntimeException(".");
}
}
public static void methodA(final Context context,
final String string1,
) throws exception {
initializedLatch.countDown();
}
public static void methodB(@NonNull final CustomObject customObjectInput) {
customObject = customObjectInput;
}
}
测试类:
import android.content.Context;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import java.util.concurrent.CountDownLatch;
import **.CustomObject;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.verify;
@RunWith(MockitoJUnitRunner.class)
public class CustomClassTest{
@Mock
static CustomObject customObject;
@Mock
static Context context;
@Mock
CountDownLatch mCountDownLatch;
@Mock
CountDownLatch mInitializedLatch;
@InjectMocks
CustomClass customClass;
@Before
public void setUp() {
customObject = Mockito.spy(CustomObject.class);
context = Mockito.spy(Context.class);
}
@Test
public void customClassTest() {
doNothing().when(mInitializedLatch).countDown();
CustomClass.methodB(customObject);
try {
CustomClass.methodA(context, "");
} catch (Exception e) {
e.printStackTrace();
}
verify(mInitializedLatch).countDown();
try {
doNothing().when(mInitializedLatch).await();
} catch (InterruptedException e) {
e.printStackTrace();
}
Class.getCustomObject();
}
我在运行 customClassTest 时收到的具体消息:
Wanted but not invoked:
mInitializedLatch.countDown();
-> at CustomClassTest.methodA(CustomClassTest.java:79)
Actually, there were zero interactions with this mock.
Wanted but not invoked:
mInitializedLatch.countDown();
-> at CustomClassTest.methodA(CustomClassTest.java:79)
Actually, there were zero interactions with this mock.
在每个相关行处运行带有断点的调试器似乎表明测试运行良好(所有变量都在正确的点正确分配)直到 verify(mInitializedLatch).countDown();,当消息出现时(并且代码停止运行)。
任何帮助表示赞赏,谢谢。
更新#1:
更改代码以删除静态关键字:
import android.content.Context;
import android.util.Log;
import **.CustomObject;
import java.util.concurrent.CountDownLatch;
import androidx.annotation.NonNull;
public class CustomClass {
private final String string = "a";
private CustomObject customObject = null;
private CountDownLatch initializedLatch = new CountDownLatch(1);
@NonNull
public CustomObject1 getCustomObject1() {
try {
initializedLatch.await();
assert customObject != null;
return customObject;
} catch (InterruptedException e) {
throw new RuntimeException(".");
}
}
public void methodA(final Context context,
final String string1,
) throws exception {
initializedLatch.countDown();
}
public void methodB(@NonNull final CustomObject customObjectInput) {
customObject = customObjectInput;
}
}
import android.content.Context;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import java.util.concurrent.CountDownLatch;
import **.CustomObject;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.verify;
@RunWith(MockitoJUnitRunner.class)
public class CustomClassTest{
@Mock
CustomObject customObject;
@Mock
Context context;
@Mock
CountDownLatch mCountDownLatch;
@Mock
CountDownLatch mInitializedLatch;
@InjectMocks
CustomClass customClass;
@Before
public void setUp() {
customObject = Mockito.spy(CustomObject.class);
context = Mockito.spy(Context.class);
}
@Test
public void customClassTest() {
doNothing().when(mInitializedLatch).countDown();
customClass.methodB(customObject);
try {
customClass.methodA(context, "");
} catch (Exception e) {
e.printStackTrace();
}
verify(mInitializedLatch).countDown();
try {
doNothing().when(mInitializedLatch).await();
} catch (InterruptedException e) {
e.printStackTrace();
}
customClass.getCustomObject();
}
错误消息现在阅读:
error: non-static method methodA(Context,String) cannot be referenced from a static context
error: non-static method getCustomObject1() cannot be referenced from a static context
第二条错误消息显示六次。似乎代码没有编译。
解决方案
在 CustomClass 中,CountDownLatch 被声明为静态字段并被初始化。如果你调试你的类,你可以看到 Mockito 没有模拟/代理这个字段。所有与 initializedLatch 对象的代码交互都不会被 Mockito 代理拦截,所以当你通过 doNothing().when(mInitializedLatch).countDown() 设置测试时,实际上你并没有将字段设置为 customClass。所以当你使用 verify(mInitializedLatch).countDown(),您实际上是在对 Mockito 说您希望与此模拟进行一次交互,但由于上述原因,没有进行交互。
推荐阅读
- arrays - 无法在 Postman 中将数组定义为变量
- powershell - 如何使用powershell查找文件并获取路径?
- python - 当我使用 configure_options 使用 add_file_option 将文件发送到我的节点时,为什么 python 会冻结?
- android - 当cordova构建android --angular时点击javax.net.ssl.SSLHandshakeException
- c# - 这两个来自不同类的 FileStreamResult 有什么区别?
- c# - .Net Standard 项目中的资源未添加到 DLL
- scala - 为什么我的 spark 作业在 collectasMap 时被阻塞
- python - 订购seaborn箱线图的y轴?
- python - 在 Seaborn 图中获取 LaTeX 符号,而不会弄乱 Pandas 查询
- r - 为什么我的 for 循环不是每次都重新分配数据帧?