2015-09-03 14 views
20

Io corro i miei test utilizzando gradle testFlavorTypePerché il test dell'unità JSONObject non è riuscito?

JSONObject jsonObject1 = new JSONObject(); 
JSONObject jsonObject2 = new JSONObject(); 
jsonObject1.put("test", "test"); 
jsonObject2.put("test", "test"); 
assertEquals(jsonObject1.get("test"), jsonObject2.get("test")); 

La prova di cui sopra ha esito positivo.

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); 

Ma le due richieste precedenti non riescono. La traccia dello stack dice che channelAssertion e messageAssertion sono nulli, ma non sono sicuro del perché. La mia domanda è: Perché i due affermati sopra non stanno funzionando?

Di seguito è il 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 
} 

riportano di seguito le stacktrace:

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) 

EDIT 17:55 EST

ho capito che posso accedere con System.out.println("") e poi vedere i risultati eseguendo gradle testFlavorType --debug e per tentativi ed errori ho scoperto la seguente strana situazione:

@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; 
} 

Per qualche motivo, "Non ci sono le chiavi ????" sta stampando?!?!?!?! Perché?!

EDIT 18:20 EST

ho capito come eseguire il debug di test di unità. Secondo il debugger, il JSONObject assegnato restituisce "null". Non ho idea di cosa significhi (vedi sotto). Dal momento che penso che questo sia rilevante, il mio file Gradle include quanto segue:

testOptions { 
    unitTests.returnDefaultValues = true 
} 

E 'particolarmente strano perché se io costruisco un JSONObject all'interno del test, quindi tutto funziona bene. Ma se fa parte del codice dell'applicazione originale, quindi non funziona e fa quanto sopra.

enter image description here

+0

Aggiungere la traccia dello stack. –

+0

@ Zoltán, ho aggiunto la traccia dello stack. – tambykojak

+0

Un tempo funzionava, ma sembra che debba essere eseguito sotto artefatto di strumentazione ora. – mbmc

risposta

28

La classe JSONObject fa parte dell'SDK di Android. Ciò significa che non è disponibile per il test delle unità di default.

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

Il file android.jar che viene utilizzato per eseguire test di unità non contiene alcun codice effettivo - che è fornito da l'immagine del sistema Android su dispositivi reali .Invece, tutti i metodi generano eccezioni (per impostazione predefinita). Questo è per assicurarti che l'unità test collauda solo il tuo codice e non dipenda da alcun particolare comportamento della piattaforma Android (che non hai deriso esplicitamente, ad esempio usando Mockito).

Quando si impostano le opzioni di test per

testOptions { 
    unitTests.returnDefaultValues = true 
} 

si fissa il "Metodo ... non deriso". problema, ma il risultato è che quando il tuo codice usa new JSONObject() non stai usando il metodo reale, stai usando un metodo di simulazione che non fa nulla, restituisce solo un valore predefinito. Questa è la ragione per cui l'oggetto è null.

Si possono trovare diversi modi di risolvere il problema in questa domanda: Android methods are not mocked when using Mockito

0

Beh, la mia prima impressione è che il metodo restituisce getMessage()null. Puoi mostrare il corpo di quel metodo nella tua domanda e trovarci la risposta, ma probabilmente dovresti cercare come eseguire il debug delle applicazioni Android usando i breakpoint.
In questo modo è possibile eseguire il codice passo dopo passo e visualizzare i valori di ciascuna variabile ad ogni passaggio. Questo ti mostrerebbe il tuo problema in poco tempo, ed è un'abilità che dovresti padroneggiare il prima possibile se vuoi impegnarti seriamente nella programmazione.

+0

Grazie per la risposta e il suggerimento. Ho già fornito il corpo del metodo 'getMessage()'. Fa parte del 'SlackMessageRequest', hai visto? Non vedo come potrebbe essere nullo comunque. Sono abbastanza familiare con il debug, ma sto eseguendo questi test nel terminale, quindi non ho trovato un modo per eseguire il debug. Qualche suggerimento su come posso ottenerlo? – tambykojak

+0

@tambykojak forse questo può aiutare https://www.bignerdranch.com/blog/triumph-android-studio-1-2-sneaks-in-full-testing-support/ la mia prossima impressione sarebbe quel 'messaggio' e 'channel' sono' null' quando vengono passati al costruttore. Non hai mostrato la parte di codice in cui hai inizializzato quelle variabili. Se l'impostazione di un ambiente di debug è troppo complicata, è sempre possibile aggiungere la registrazione temporanea tra alcune linee. –

+0

Ho letto quel blog più volte, ma non risolve questo problema. Anche se 'channel' e' test' sono 'null', il test dovrebbe comunque passare in base alla logica fornita. – tambykojak

19

Come Lucas dice, JSON è fornito in bundle con l'SDK di Android, quindi si sta lavorando con un mozzicone.

La soluzione attuale è quella di tirare JSON da Maven centrale in questo modo:

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

In alternativa, è possibile scaricare e includere il vaso:

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

È not known quale versione del manufatto Maven corrisponde esattamente/più strettamente a ciò che viene fornito con Android.

Nota che devi utilizzare anche Android Studio 1.1 o versione successiva e almeno creare strumenti versione 22.0.0 o successiva affinché funzioni.

Problema correlato: #179461

+0

Questo non funziona più per me. Ha funzionato su un vecchio progetto, ma ora sto ancora ottenendo 'null' quando provo a creare un nuovo' JSONObject'. Sto usando 'testCompile 'org.json: json: 20160810''. Ho anche provato 'configurations.all {resolutionStrategy.force 'org.json: json: 20160810'}', ma senza fortuna. Qualche idea? – AutonomousApps

+0

Ho appena trovato questo nel mio output gradle: 'ATTENZIONE: Dipendenza org.json: json: 20160810 viene ignorata per flavorDebug in quanto potrebbe essere in conflitto con la versione interna fornita da Android. In caso di problemi, si prega di riconfezionare con jarjar per modificare i pacchetti di classe' – AutonomousApps

+0

Grazie. Non hai idea di quanto questa soluzione aiuti la mia pressione sanguigna. – jwehrle

Problemi correlati