Java 为什么我的 JSONObject 相关单元测试失败?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32385092/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why is my JSONObject related unit test failing?
提问by tambykojak
I'm running my tests using gradle testFlavorType
我正在运行我的测试 gradle testFlavorType
JSONObject jsonObject1 = new JSONObject();
JSONObject jsonObject2 = new JSONObject();
jsonObject1.put("test", "test");
jsonObject2.put("test", "test");
assertEquals(jsonObject1.get("test"), jsonObject2.get("test"));
The above test succeeds.
以上测试成功。
jsonObject = new SlackMessageRequest(channel, message).buildBody();
String channelAssertion = jsonObject.getString(SlackMessageRequest.JSON_KEY_CHANNEL);
String messageAssertion = jsonObject.getString(SlackMessageRequest.JSON_KEY_TEXT);
assertEquals(channel, channelAssertion);
assertEquals(message, messageAssertion);
But the above two requests fail. The stack trace says that channelAssertion and messageAssertion are null, but not sure why. My question is: Why are the above two asserts failing?
但是上面两个请求都失败了。堆栈跟踪说 channelAssertion 和 messageAssertion 为空,但不确定为什么。我的问题是:为什么上述两个断言失败?
Below is the SlackMessageRequest
.
下面是SlackMessageRequest
.
public class SlackMessageRequest
extends BaseRequest {
// region Variables
public static final String JSON_KEY_TEXT = "text";
public static final String JSON_KEY_CHANNEL = "channel";
private String mChannel;
private String mMessage;
// endregion
// region Constructors
public SlackMessageRequest(String channel, String message) {
mChannel = channel;
mMessage = message;
}
// endregion
// region Methods
@Override
public MethodType getMethodType() {
return MethodType.POST;
}
@Override
public JSONObject buildBody() throws JSONException {
JSONObject body = new JSONObject();
body.put(JSON_KEY_TEXT, getMessage());
body.put(JSON_KEY_CHANNEL, getChannel());
return body;
}
@Override
public String getUrl() {
return "http://localhost:1337";
}
public String getMessage() {
return mMessage;
}
public String getChannel() {
return mChannel;
}
// endregion
}
Below is the stacktrace:
以下是堆栈跟踪:
junit.framework.ComparisonFailure: expected:<@tk> but was:<null>
at junit.framework.Assert.assertEquals(Assert.java:100)
at junit.framework.Assert.assertEquals(Assert.java:107)
at junit.framework.TestCase.assertEquals(TestCase.java:269)
at com.example.app.http.request.SlackMessageRequestTest.testBuildBody(SlackMessageRequestTest.java:30)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at junit.framework.TestCase.runTest(TestCase.java:176)
at junit.framework.TestCase.runBare(TestCase.java:141)
at junit.framework.TestResult.protect(TestResult.java:122)
at junit.framework.TestResult.runProtected(TestResult.java:142)
at junit.framework.TestResult.run(TestResult.java:125)
at junit.framework.TestCase.run(TestCase.java:129)
at junit.framework.TestSuite.runTest(TestSuite.java:252)
at junit.framework.TestSuite.run(TestSuite.java:247)
at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:86)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:86)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:49)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:64)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:50)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.messaging.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
at org.gradle.messaging.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:106)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.messaging.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:360)
at org.gradle.internal.concurrent.DefaultExecutorFactory$StoppableExecutorImpl.run(DefaultExecutorFactory.java:64)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
EDIT 5:55PM EST
编辑美国东部时间下午 5:55
I've figured out that I can log with System.out.println("")
and then see the results by running gradle testFlavorType --debug
and by trial and error I've discovered the following weird situation:
我发现我可以登录,System.out.println("")
然后通过运行gradle testFlavorType --debug
和反复试验来查看结果我发现了以下奇怪的情况:
@Override
public JSONObject buildBody() throws JSONException {
System.out.println("buildBody mChannel = " + mChannel);
System.out.println("buildBody mMessage = " + mMessage);
JSONObject body = new JSONObject();
body.put(JSON_KEY_TEXT, getMessage());
body.put(JSON_KEY_CHANNEL, getChannel());
if (body.length() != 0) {
Iterator<String> keys = body.keys();
if (keys.hasNext()) {
do {
String key = keys.next();
System.out.println("keys: " + key);
} while (keys.hasNext());
}
} else {
System.out.println("There are no keys????");
}
return body;
}
For some reason, "There are no keys????" is printing out?!?!?!?! Why?!
出于某种原因,“没有钥匙???” 打印出来了吗?!?!?!?!为什么?!
EDIT 6:20PM EST
编辑东部时间下午 6:20
I've figured out how to debug unit tests. According to the debugger, the assigned JSONObject is returning "null"
. I have no clue what this means (see below). Since I think this is relevant, my gradle file includes the following:
我已经想出了如何调试单元测试。根据调试器,分配的 JSONObject 正在返回"null"
. 我不知道这意味着什么(见下文)。由于我认为这是相关的,因此我的 gradle 文件包含以下内容:
testOptions {
unitTests.returnDefaultValues = true
}
It's especially strange because if I construct a JSONObject inside the test, then everything works fine. But if it is part of the original application's code, then it doesn't work and does the above.
这特别奇怪,因为如果我在测试中构造一个 JSONObject,那么一切正常。但如果它是原始应用程序代码的一部分,则它不起作用并执行上述操作。
采纳答案by David Miguel
As Lucas says, JSON is bundled up with the Android SDK, so you are working with a stub.
正如 Lucas 所说,JSON 与 Android SDK 捆绑在一起,因此您正在使用存根。
The current solution is to pull JSON from Maven Central like this:
当前的解决方案是从 Maven Central 中提取 JSON,如下所示:
dependencies {
...
testCompile 'org.json:json:20190722'
}
You can replace the version 20190722
with the the latest onedepending on the Android API. It is not knownwhich version of the maven artifact corresponds exactly/most closely to what ships with Android.
您可以替换的版本20190722
与最新的一个取决于Android的API。这是不知道的Maven构件对应的版本完全相同/最密切到什么附带的Android。
Alternatively, you can download and include the jar:
或者,您可以下载并包含 jar:
dependencies {
...
testCompile files('libs/json.jar')
}
Note that you also need to use Android Studio 1.1 or higher and at least build tools version 22.0.0 or above for this to work.
请注意,您还需要使用 Android Studio 1.1 或更高版本以及至少 22.0.0 或更高版本的构建工具才能使其正常工作。
Related issue: #179461
相关问题:#179461
回答by Zoltán
Well, my first hunch would be that your getMessage()
method returns null
. You could show the body of that method in your question and have us find the answer for you, but you should probably research how to debug android applications using breakpoints.
That way you can run your code step by step and see the values of each variable at every step. That would show you your problem in no time, and it's a skill you should definitely master as soon as possible if you intend to get seriously involved in programming.
好吧,我的第一个预感是您的getMessage()
方法返回null
. 您可以在问题中显示该方法的主体,让我们为您找到答案,但您可能应该研究如何使用断点调试 android 应用程序。
这样您就可以逐步运行您的代码并查看每一步中每个变量的值。这将立即向您展示您的问题,如果您打算认真参与编程,那么您绝对应该尽快掌握这项技能。
回答by Lucas L.
The class JSONObject is part of the android SDK. That means that is not available for unit testing by default.
类 JSONObject 是 android SDK 的一部分。这意味着默认情况下不可用于单元测试。
From http://tools.android.com/tech-docs/unit-testing-support
来自http://tools.android.com/tech-docs/unit-testing-support
The android.jar file that is used to run unit tests does not contain any actual code - that is provided by the Android system image on real devices. Instead, all methods throw exceptions (by default). This is to make sure your unit tests only test your code and do not depend on any particular behaviour of the Android platform (that you have not explicitly mocked e.g. using Mockito).
用于运行单元测试的 android.jar 文件不包含任何实际代码 - 由真实设备上的 Android 系统映像提供。相反,所有方法都会抛出异常(默认情况下)。这是为了确保您的单元测试仅测试您的代码,而不依赖于 Android 平台的任何特定行为(您没有明确模拟,例如使用 Mockito)。
When you set the test options to
当您将测试选项设置为
testOptions {
unitTests.returnDefaultValues = true
}
you are fixing the "Method ... not mocked." problem, but the outcome is that when your code uses new JSONObject()
you are not using the real method, you are using a mock method that doesn't do anything, it just returns a default value. That's the reason the object is null
.
您正在修复“方法......没有被嘲笑”。问题,但结果是,当您的代码使用时,new JSONObject()
您没有使用真正的方法,而是使用了一个什么都不做的模拟方法,它只返回一个默认值。这就是对象是 的原因null
。
You can find different ways of solving the problem in this question: Android methods are not mocked when using Mockito
你可以在这个问题中找到解决问题的不同方法:Android methods are not mocked when using Mockito