簡體   English   中英

為什么我的 JSONObject 相關單元測試失敗?

[英]Why is my JSONObject related unit test failing?

我正在使用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 為空,但不確定為什么。 我的問題是:為什么上述兩個斷言失敗?

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

我發現我可以使用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

我已經想出了如何調試單元測試。 根據調試器,分配的 JSONObject 返回"null" 我不知道這意味着什么(見下文)。 由於我認為這是相關的,因此我的 gradle 文件包含以下內容:

testOptions {
    unitTests.returnDefaultValues = true
}

這特別奇怪,因為如果我在測試中構造一個 JSONObject,那么一切正常。 但如果它是原始應用程序代碼的一部分,則它不起作用並執行上述操作。

在此處輸入圖片說明

正如 Lucas 所說,JSON 與 Android SDK 捆綁在一起,因此您正在使用存根。

當前的解決方案是從 Maven Central 中提取 JSON,如下所示:

dependencies {
    ...
    testImplementation 'org.json:json:20201115'
}

您可以根據 Android API 將20201115版本替換為最新版本。 不知道哪個版本的 maven 人工制品與 Android 附帶的版本完全/最接近。

或者,您可以下載並包含 jar:

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

請注意,您還需要使用 Android Studio 1.1 或更高版本以及至少 22.0.0 或更高版本的構建工具才能使其工作。

相關問題: #179461

類 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

好吧,我的第一個預感是您的getMessage()方法返回null 您可以在問題中顯示該方法的主體,讓我們為您找到答案,但您可能應該研究如何使用斷點調試 android 應用程序。
這樣您就可以逐步運行您的代碼並查看每一步中每個變量的值。 這將立即向您展示您的問題,如果您打算認真參與編程,那么您絕對應該盡快掌握這項技能。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM