MockitoとJUnit4を使用して、以下のコードの単体テストを作成するのに助けが必要です。
public class MyFragmentPresenterImpl {
public Boolean isValid(String value) {
return !(TextUtils.isEmpty(value));
}
}
私は以下の方法を試しました:MyFragmentPresenter mMyFragmentPresenter
@Before
public void setup(){
mMyFragmentPresenter=new MyFragmentPresenterImpl();
}
@Test
public void testEmptyValue() throws Exception {
String value=null;
assertFalse(mMyFragmentPresenter.isValid(value));
}
ただし、次の例外を返します。
Java.lang.RuntimeException:Android.text.TextUtilsのメソッドisEmptyはモックされていません。詳細については、 http://g.co/androidstudio/not-mocked を参照してください。 Android.text.TextUtils.isEmpty(TextUtils.Java)at ....
JUnit TestCaseクラスではAndroid関連APIを使用できないため、モックする必要があります。PowerMockito
を使用して、静的クラスをモックします。
テストケースクラスの上に2行追加し、
_@RunWith(PowerMockRunner.class)
@PrepareForTest(TextUtils.class)
public class YourTest
{
}
_
そしてセットアップコード
_@Before
public void setup() {
PowerMockito.mockStatic(TextUtils.class);
PowerMockito.when(TextUtils.isEmpty(any(CharSequence.class))).thenAnswer(new Answer<Boolean>() {
@Override
public Boolean answer(InvocationOnMock invocation) throws Throwable {
CharSequence a = (CharSequence) invocation.getArguments()[0];
return !(a != null && a.length() > 0);
}
});
}
_
TextUtils.isEmpty()
を独自のロジックで実装します。
また、依存関係を_app.gradle
_ファイルに追加します。
_testCompile "org.powermock:powermock-module-junit4:1.6.2"
testCompile "org.powermock:powermock-module-junit4-rule:1.6.2"
testCompile "org.powermock:powermock-api-mockito:1.6.2"
testCompile "org.powermock:powermock-classloading-xstream:1.6.2"
_
Behelit
とException
の回答に感謝します。
PowerMockitoを使用する
これをクラス名の上に追加し、他のCUTクラス名(テスト対象のクラス)を含めます
@RunWith(PowerMockRunner.class)
@PrepareForTest({TextUtils.class})
public class ContactUtilsTest
{
これを@Beforeに追加します
@Before
public void setup(){
PowerMockito.mockStatic(TextUtils.class);
mMyFragmentPresenter=new MyFragmentPresenterImpl();
}
これにより、PowerMockitoはTextUtils内のメソッドのデフォルト値を返します。
関連するgradle depedenciesも追加する必要があります
testCompile "org.powermock:powermock-module-junit4:1.6.2"
testCompile "org.powermock:powermock-module-junit4-rule:1.6.2"
testCompile "org.powermock:powermock-api-mockito:1.6.2"
testCompile "org.powermock:powermock-classloading-xstream:1.6.2"
これは、@ Exceptionで言及されている既知の問題です。私の場合、私も同じ状況に出くわしましたが、上級開発者のアドバイスにより、Strings.isNullOrEmpty()
の代わりにTextUtils.isEmpty()
を使用することにしました。それを回避する良い方法であることが判明しました。
更新:このユーティリティ関数 Strings.isNullOrEmpty()
にはGuavaライブラリが必要であることに言及する必要があります。
Android Studioの場合、gradleファイルにこの行を追加します。
Android{
....
testOptions {
unitTests.returnDefaultValues = true
}
}
これは既知の問題です。TestingFundamentalのAndroidの句:
JUnit TestCaseクラスを使用して、Android APIsを呼び出さないクラスでユニットテストを実行できます。
Log
やTextUtils
などのクラスを使用する場合、デフォルトの動作には問題があります。
総括する:
Android.jar
は以前は模擬であるため、一部のAndroid APIの戻り値は期待どおりではない可能性があります。出典:http://www.liangfeizc.com/2016/01/28/unit-test-on-Android/ =
次のテストクラスを実行して、このエラーを解決できました。
@RunWith(RobolectricGradleTestRunner.class)public class MySimpleTest {..... a束のテストケース}
このWikiページでは、より詳細に説明しています https://github.com/yahoo/squidb/wiki/Unit-testing-with-model-objects
私は私のプロジェクトTextUtils.isEmpty(...)
のすべてをこれで置き換えます:
/**
* Util class to be used instead of Android classes for Junit tests.
*/
public class Utils {
/**
* Returns true if the string is null or 0-length.
* @param str the string to be examined
* @return true if str is null or zero length
*/
public static boolean isEmpty(@Nullable CharSequence str) {
return str == null || str.length() == 0;
}
}
Robolectricを使用する必要があります。
testImplementation "org.robolectric:robolectric:3.4.2"
その後
@RunWith(RobolectricTestRunner::class)
class TestClass {
...
}
ジョニーの答えのフォローアップとして、TextUtils.isEmpty(null)呼び出しもキャッチするには、このコードを使用できます。
PowerMockito.mockStatic(TextUtils.class);
PowerMockito.when(TextUtils.isEmpty(any()))
.thenAnswer((Answer<Boolean>) invocation -> {
Object s = invocation.getArguments()[0];
return s == null || s.length() == 0;
});
解決策1:
KotlinとJavaバージョンを提供したいと思います。
Kotlinバージョン:
import Android.text.TextUtils
import org.junit.Before
import org.junit.runner.RunWith
import org.mockito.Matchers.any
import org.powermock.api.mockito.PowerMockito
import org.powermock.core.classloader.annotations.PrepareForTest
import org.powermock.modules.junit4.PowerMockRunner
@RunWith(PowerMockRunner::class)
@PrepareForTest(TextUtils::class)
class UserOwnedDataTest1 {
@Before
fun setup() {
PowerMockito.mockStatic(TextUtils::class.Java)
PowerMockito.`when`(TextUtils.isEmpty(any(CharSequence::class.Java))).thenAnswer { invocation ->
val a = invocation.arguments[0] as? CharSequence
a?.isEmpty() ?: true
}
}
}
Javaバージョン:
import Android.text.TextUtils;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.mockito.stubbing.Answer;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.mockito.Matchers.any;
@RunWith(PowerMockRunner.class)
@PrepareForTest(TextUtils.class)
public final class UserOwnedDataTest2 {
@Before
public void setup() {
PowerMockito.mockStatic(TextUtils.class);
PowerMockito.when(TextUtils.isEmpty(any(CharSequence.class))).thenAnswer((Answer<Boolean>) invocation -> {
CharSequence a = (CharSequence) invocation.getArguments()[0];
return !(a != null && a.length() > 0);
});
}
}
依存関係を追加することを忘れないでください:
testCompile "org.powermock:powermock-module-junit4:1.6.2"
testCompile "org.powermock:powermock-module-junit4-rule:1.6.2"
testCompile "org.powermock:powermock-api-mockito:1.6.2"
testCompile "org.powermock:powermock-classloading-xstream:1.6.2"
私たちはまだ別の依存関係を必要としていることを覚えていますが、明確ではありません。
とにかく、不足している依存関係を簡単に修正できます。
解決策2:
または、TextUtilsで同じパッケージとクラス名を追加できます
package Android.text;
public class TextUtils {
public static boolean isEmpty( CharSequence str) {
return str == null || str.length() == 0;
}
}