【问题标题】:How its the correct way to test a serielize method inside a class?在类中测试序列化方法的正确方法是什么?
【发布时间】:2015-12-13 05:22:34
【问题描述】:

我在一个类里面有这个方法,它将类的属性序列化到一个JSONObject中,很简单:

public String serialize(){
    JSONObject wifiToAddJson = null;
    try {
        wifiToAddJson = new JSONObject();
        wifiToAddJson.put("wifi_ssid", wifi_ssid);
        wifiToAddJson.put("wifi_password", wifi_password);
        wifiToAddJson.put("latitude", wifi_LatLng.latitude);
        wifiToAddJson.put("longitude", wifi_LatLng.longitude);
        wifiToAddJson.put("name", name);
    } catch (JSONException e) {
        ACRA.getErrorReporter().handleSilentException(new MyJSONException(TAG + e.getMessage()));
    }
    return wifiToAddJson.toString();
}

我想通过询问所有字段的值来测试这种方法是否可以。 我想通过这样的测试来做到这一点:

@Test
public void testSerialize(){
    String wifiSerialized = wiFiToAdd.serialize();

    try {
        JSONObject jsonObject = new JSONObject(wifiSerialized);

        String ssid = (String) jsonObject.get("wifi_ssid");
        String password = (String) jsonObject.get("wifi_password");
        String name = (String) jsonObject.get("name");
        String latitude = (String) jsonObject.get("latitude");
        String longitude = (String) jsonObject.get("longitude");

        assertEquals("WIFI_TEST", ssid);
        assertEquals("wifiTest", password);
        assertEquals("WiFi Pruebas", name);
        assertEquals("40.420088", latitude);
        assertEquals("-3.688810", longitude);

    } catch (JSONException e) {
        e.printStackTrace();
    }
}

但是问题来了:

java.lang.RuntimeException: Method put in org.json.JSONObject not mocked. See https://sites.google.com/a/android.com/tools/tech-docs/unit-testing-support for details.
    at org.json.JSONObject.put(JSONObject.java)
    at com.wiffinity.easyaccess.model.wifi.WiFiToAdd.serialize(WiFiToAdd.java:32)
    at com.wiffinity.easyaccess.model.wifi.WiFiToAddTest.testSerialize(WiFiToAddTest.java:28)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:79)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)


Process finished with exit code -1

谷歌文档说:

用于运行单元测试的 android.jar 文件不包含任何实际代码 - 由真实设备上的 Android 系统映像提供。相反,所有方法都会抛出异常(默认情况下)。这是为了确保您的单元测试仅测试您的代码,而不依赖于 Android 平台的任何特定行为(您没有明确模拟,例如使用 Mockito)。如果这证明有问题,您可以将下面的 sn-p 添加到您的 build.gradle 以更改此行为:

android {
// ...

    testOptions { 
        unitTests.returnDefaultValues = true
    }
}

我不想改变我的测试的整体行为。如何以干净的方式测试该方法而不改变测试的行为?

【问题讨论】:

标签: java android unit-testing


【解决方案1】:

你可以把你的serialize方法剪成2:

public void serializeInto(JSONObject target) throws JSONException {
    wifiToAddJson.put("wifi_ssid", wifi_ssid);
    wifiToAddJson.put("wifi_password", wifi_password);
    wifiToAddJson.put("latitude", wifi_LatLng.latitude);
    wifiToAddJson.put("longitude", wifi_LatLng.longitude);
    wifiToAddJson.put("name", name);
}

public String serialize(){
    JSONObject wifiToAddJson = null;
    try {
        wifiToAddJson = new JSONObject();
        serializeInto(wifiToAddJson);
    } catch (JSONException e) {
        ACRA.getErrorReporter().handleSilentException(new MyJSONException(TAG + e.getMessage()));
    }
    return wifiToAddJson.toString();
}

然后用模拟的JSONObject 测试第一个,用你的类的模拟测试第二个(只是验证方法serialize 被调用)。

我对这个答案并不完全满意,因为你不会达到 100% 的覆盖率,而且我觉得它会降低代码的可读性。

【讨论】:

  • 我不确定在两个公共方法中更改“工作”公共方法只是为了测试它。这当然是一种可能。我会记住的。
【解决方案2】:

将此添加到您的 build.gradle 文件中:

testCompile 'org.json:json:20160810' // org.json is included with Android, but Android.jar can not be used from unit tests

它将使您的单元测试直接使用 JSON 库,而不是 Android 中包含的那个。

更多详情请见this StackOverflow answer

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多