2016-04-25 2 views
6

Je sais que c'est bizarre, mais c'est ce que j'ai.JUnit4 TextUtils.isEmpty() donne un résultat différent de String.isEmpty()

enter image description here

J'écris un test unitaire pour vérifier ma logique pour une application Android. Au cours de l'exécution du test, je vois qu'il échoue sur cette ligne:

if (!TextUtils.isEmpty(fromFile))

Avant cette déclaration if FROMFILE est égal à "" (chaîne vide), mais en quelque sorte, il passe au-dessus et rompt avec une autre logique qui doesn Ne vous attendez pas à une chaîne vide. Plonger dans le débogage J'ai vu que fromFile.isEmpty() renvoie le résultat correct, mais TextUtils.isEmpty(fromFile) indique qu'il n'est pas vide.

code source libre, je vois:

public static boolean isEmpty(@Nullable CharSequence str) { 
    if (str == null || str.length() == 0) 
     return true; 
    else 
     return false; 
} 

et String.java:

public boolean isEmpty() { 
    return value.length == 0; 
} 

Je suit configutation: jdk 1.8.0_77

Je voudrais éviter toute logique dans l'application pour soutenir String.isEmpty() juste pour passer le test, car je dois supporter le code avant Android API 9, où String.isEmpty n'est pas disponible, et al donc TextUtils.isEmpty() faire plus. Toute aide avec des éclaircissements et des suggestions serait utile.

Quelqu'un at-il fait face? Comment devrais-je le réparer? Merci d'avance!

Répondre

7

Pour tous ceux qui feront face à l'avenir:

J'ai compris ce à l'aide de bon homme, qu'il est lié à la configuration de test unitaire android dans gradle:

testOptions { 
    unitTests.returnDefaultValues = true 
} 

qui a moi à une solution: débarrassez-vous des dépendances android dans votre logique commerciale que vous testez avec JUnit (test unitaire).

J'ai simplement remplacé android.text.TextUtils avec ma propre méthode qui est dans la classe MyStringUtils.java, qui fait la même chose. Problème: les méthodes Android de deault ont renvoyé des valeurs inattendues lors de l'exécution du test unitaire et n'ont pas vérifié la valeur fromFile elle-même, mais plutôt la valeur stub/default.

+0

Mais est-ce s une solution? Je veux dire pour ce cas que vous avez seulement TextUtils, mais que se passe-t-il si vous utilisez SparsArrays et une autre implémentation utilitaire personnalisée fournie par Android? – karate

+0

l'idée des tests purs JUnit est qu'ils doivent être utilisés contre POJO (Plain Old Java Object). 'SparseArrays' ne sont pas Old Java. Si vous l'avez, vous pouvez aller avec http://robolectric.org/, ce qui est totalement bien selon google https://developer.android.com/training/testing/fundamentals.html –

1

TextUtils n'est pas une méthode JUnit.Si vous avez besoin de manipuler avec TextUtils.isEmpty réponse ou une autre méthode, vous pouvez moquer comme:

mockStatic(TextUtils.class); 
when(TextUtils.isEmpty(any(CharSequence.class))).thenAnswer(new Answer<Boolean>() { 
     @Override 
     public Boolean answer(InvocationOnMock invocation) throws Throwable { 
      CharSequence str = (CharSequence) invocation.getArguments()[0]; 
      if (str == null || str.length() == 0) 
       return true; 
      else 
       return false; 
     } 
    }); 

Ne pas oublier d'ajouter TextUtils-PrepareForTest liste:

@PrepareForTest({TextUtils.class}) 

méthode également mentionnée ci-dessus fonctionne pour returnDefaultValues configuration:

testOptions { 
    unitTests.returnDefaultValues = true 
} 
+0

Malheureusement, nous n'utilisons pas ' Powermock' et 'mockStatic' ne sont pas applicables. Nous sommes passés à l'architecture différente, où nos classes Java sont POJO et n'ont pas de dépendances android. Nous nous sommes également éloignés des méthodes statiques comme 'Utils.doSomething' et en supprimant les singletons. Cela nous donne plus de contrôle de DI et de couverture de test. Pour autant que je sache, codecov ne supporte pas 'PowerMockito'. Mais merci pour votre réponse, je suppose que beaucoup de développeurs le trouveront utile aussi. –