Подтвердить что ты не робот

Почему мой JSONObject связан с unit test ошибкой?

Я запускаю свои тесты, используя 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 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 внутри теста, тогда все работает нормально. Но если это часть исходного кода приложения, то он не работает и делает это.

введите описание изображения здесь

4b9b3361

Ответ 1

Класс JSONObject является частью SDK android. Это означает, что по умолчанию не доступно для модульного тестирования.

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

Файл android.jar, который используется для запуска модульных тестов, не содержит любой фактический код, который предоставляется на изображении системы Android на реальном устройства. Вместо этого все методы генерируют исключения (по умолчанию). Это чтобы убедиться, что ваш блок тестирует только ваш код и не зависит от любое конкретное поведение платформы Android (у вас нет явно издевается, например. используя Mockito).

При настройке параметров тестирования

testOptions {
    unitTests.returnDefaultValues = true
}

вы исправляете "Метод... не издеваетесь". проблема, но результат заключается в том, что когда ваш код использует new JSONObject(), вы не используете настоящий метод, вы используете метод макета, который ничего не делает, он просто возвращает значение по умолчанию. Это причина, по которой объект null.

Вы можете найти различные способы решения проблемы в этом вопросе: Android-методы не издеваются при использовании Mockito

Ответ 2

Как говорит Лукас, JSON связан с Android SDK, поэтому вы работаете с заглушкой.

Текущее решение - извлечь JSON из Maven Central следующим образом:

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

Кроме того, вы можете скачать и включить банку:

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

Это не известно, какая версия Maven артефакта точно соответствует/наиболее близко к каким судам с Android.

Обратите внимание, что вам также нужно использовать Android Studio 1.1 или выше и, по крайней мере, инструменты сборки версии 22.0.0 или выше, чтобы это работало.

Похожие проблемы: # 179461

Ответ 3

Хорошо, моя первая догадка заключается в том, что ваш метод getMessage() возвращает null. Вы можете показать тело этого метода в своем вопросе и найти ответ для вас, но вам, вероятно, следует изучить, как отлаживать приложения Android с помощью точек останова.
Таким образом, вы можете запускать свой код шаг за шагом и видеть значения каждой переменной на каждом шаге. Это покажет вам вашу проблему в мгновение ока, и это умение, которое вы должны обязательно освоить как можно скорее, если вы намерены серьезно заняться программированием.

Ответ 4

Я сталкиваюсь с той же проблемой, когда пытаюсь протестировать класс, который анализирует JSON. Mockito все еще был бы вариантом, но сейчас я использую intrumented или androidTests. Их можно легко создать в Android Studio. Тест выполняется на моем виртуальном устройстве Android (изображение), и я также могу отлаживать.