为什么我的JSONObject相关unit testing失败?

我正在使用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")); 

上述测试成功。

 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); 

但上述两个请求失败了。 堆栈跟踪表明channelAssertion和messageAssertion为null,但不确定原因。 我的问题是: 为什么上述两个断言都失败了?

下面是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 } 

下面是堆栈跟踪:

 junit.framework.ComparisonFailure: expected: but was: 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$1.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$1.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) 

编辑美国东部时间下午5:55

我已经发现我可以使用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 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; } 

出于某种原因,“没有钥匙????” 打印出来了?!?!?!?! 为什么?!

编辑美国东部时间下午6:20

我已经想出了如何调试unit testing。 根据调试器,分配的JSONObject返回"null" 。 我不知道这意味着什么(见下文)。 由于我认为这是相关的,我的gradle文件包括以下内容:

 testOptions { unitTests.returnDefaultValues = true } 

这特别奇怪,因为如果我在测试中构造一个JSONObject,那么一切正常。 但如果它是原始应用程序代码的一部分,那么它不起作用并执行上述操作。

在此处输入图像描述

Solutions Collecting From Web of "为什么我的JSONObject相关unit testing失败?"

JSONObject类是android SDK的一部分。 这意味着默认情况下不能进行unit testing。

来自http://tools.android.com/tech-docs/unit-testing-support

用于运行unit testing的android.jar文件不包含任何实际代码 – 由真实设备上的Android系统映像提供。 相反,所有方法都会抛出exception(默认情况下)。 这是为了确保您的unit testing仅测试您的代码,而不依赖于Android平台的任何特定行为(您没有明确嘲笑,例如使用Mockito)。

将测试选项设置为

 testOptions { unitTests.returnDefaultValues = true } 

你正在修理“方法……没有嘲笑”。 问题,但结果是,当你的代码使用new JSONObject()你没有使用真正的方法,你使用的模拟方法没有做任何事情,它只返回一个默认值。 这就是对象为null的原因。

您可以在此问题中find解决问题的不同方法: 使用Mockito时不会嘲笑Android方法

正如Lucas所说,JSON与Android SDK捆绑在一起,因此您正在使用存根。

目前的解决方案是从Maven Central中提取JSON,如下所示:

 dependencies { ... testCompile 'org.json:json:20180130' } 

或者,您可以下载并包含jar:

 dependencies { ... testCompile files('libs/json.jar') } 

目前尚不清楚哪个版本的maven工件与Android附带的版本完全/最接近。

请注意,您还需要使用Android Studio 1.1或更高版本以及至少构建工具版本22.0.0或更高版本才能使用此function。

相关问题: #179461

好吧,我的第一个预感是你的getMessage()方法返回null 。 您可以在问题中显示该方法的主体并让我们为您find答案,但您应该研究如何使用断点调试Android应用程序。
这样,您可以逐步运行代码,并在每个步骤中查看每个variables的值。 这会立即向您展示您的问题,如果您打算认真参与编程,那么您应该尽快掌握这项技能。