2015-09-03 209 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