2015-09-03 208 views
20

我使用gradle testFlavorType为什么我的JSONObject相关单元测试失败?

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为空,但不知道为什么。我的问题是:为什么上述两个断言失败?

以下是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:<@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$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 PM EST

我已经想通了,我可以记录与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; 
} 

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

编辑6:20 PM EST

我已经想通了如何调试单元测试。根据调试器,分配的JSONObject返回"null"。我不知道这意味着什么(见下文)。因为我觉得这是相关的,我gradle这个文件包含以下内容:

testOptions { 
    unitTests.returnDefaultValues = true 
} 

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

enter image description here

+0

请添加堆栈跟踪。 –

+0

@Zoltán,我添加了堆栈跟踪。 – tambykojak

+0

曾经工作,但似乎它必须现在在仪表工件下运行。 – mbmc

回答

28

JSONObject类是android SDK的一部分。这意味着默认情况下不适用于单元测试。

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

,用于运行单元测试不包含任何 实际代码的android.jar文件 - 是由真实的 设备Android系统图像提供。相反,所有方法都会引发异常(默认情况下)。这是 ,以确保您的单元测试仅测试您的代码,并且不依赖于Android平台的任何特定行为(您没有明确嘲笑例如使用Mockito的 )。

当您设置的测试选项

testOptions { 
    unitTests.returnDefaultValues = true 
} 

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

你可以找到这个问题的解决问题的方式不同:Android methods are not mocked when using Mockito

0

好了,我的第一直觉是你的getMessage()方法返回null。您可以在您的问题中显示该方法的主体,并让我们为您找到答案,但是您应该研究如何使用断点来调试android应用程序。
通过这种方式,您可以逐步运行代码并在每个步骤中查看每个变量的值。这会立即向您显示您的问题,如果您打算认真参与编程,那么您应该尽快掌握一项技能。

+0

感谢您的回答和建议。我已经提供了getMessage()方法的主体。它是'SlackMessageRequest'的一部分,你看过吗?但是我不明白它可能是空的。我对调试非常熟悉,但是我在终端上运行这些测试,所以我还没有找到一种方法来调试它们。有关我如何实现这一目标的任何建议? – tambykojak

+0

@tambykojak也许这可以帮助https://www.bignerdranch.com/blog/triumph-android-studio-1-2-sneaks-in-full-testing-support/ 我的下一个预感将是'message'和传递给构造函数时'channel'为'null'。您没有显示初始化这些变量的部分代码。如果设置调试环境太复杂,可以在一些行之间添加临时日志记录。 –

+0

我已经多次阅读过这个博客,但并没有解决这个问题。即使'channel'和'test'为'null',测试仍应该依据所提供的逻辑通过。 – tambykojak

19

至于卢卡斯说,JSON是捆绑了Android的SDK,所以你是一个存根工作。

目前的解决方案是从Maven的中央拉JSON是这样的:

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

或者,您也可以下载并包括JAR:

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

这是not known将Maven构件的版本完全对应/最接近Android附带的内容。

请注意,您还需要使用Android Studio 1.1或更高版本,并且至少需要构建工具版本22.0.0或更高版本才能运行。

相关问题:#179461

+0

这不再适用于我。它在一个旧的项目上做了,但是现在当我尝试创建一个新的'JSONObject'时,我仍然得到'null'。我正在使用'testCompile'org.json:json:20160810''。我也尝试过'configurations.all {resolutionStrategy.force'org.json:json:20160810'}',但没有运气。有任何想法吗? – AutonomousApps

+0

我刚刚在我的gradle输出中发现了这个: '警告:依赖org.json:json:20160810会被flavorDebug忽略,因为它可能与Android提供的内部版本冲突。 如有问题,请用jarjar重新包装以改变课程包# – AutonomousApps

+0

谢谢。你不知道这个解决方案对我的血压有多大帮助。 – jwehrle