web-dev-qa-db-ja.com

MockitoとJUnit4を使用して単体テストを作成するのに助けが必要

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 ....

21
Kadari

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"
_

BehelitExceptionの回答に感謝します。

37
Johnny

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"
7
behelit

これは、@ Exceptionで言及されている既知の問題です。私の場合、私も同じ状況に出くわしましたが、上級開発者のアドバイスにより、Strings.isNullOrEmpty()の代わりにTextUtils.isEmpty()を使用することにしました。それを回避する良い方法であることが判明しました。

更新:このユーティリティ関数 Strings.isNullOrEmpty() にはGuavaライブラリが必要であることに言及する必要があります。

6
Wahib Ul Haq

Android Studioの場合、gradleファイルにこの行を追加します。

Android{
....
 testOptions {
        unitTests.returnDefaultValues = true
 }
}
5
Abhishek

これは既知の問題です。TestingFundamentalのAndroidの句:

JUnit TestCaseクラスを使用して、Android APIsを呼び出さないクラスでユニットテストを実行できます。

LogTextUtilsなどのクラスを使用する場合、デフォルトの動作には問題があります。

総括する:

  1. Android.jarは以前は模擬であるため、一部のAndroid APIの戻り値は期待どおりではない可能性があります。
  2. JUnit自体はJavaコードの単一のメジャーであるため、Android APIメソッドを使用しないでください。

出典:http://www.liangfeizc.com/2016/01/28/unit-test-on-Android/ =

3
Exception

次のテストクラスを実行して、このエラーを解決できました。

@RunWith(RobolectricGradleTestRunner.class)public class MySimpleTest {..... a束のテストケース}

このWikiページでは、より詳細に説明しています https://github.com/yahoo/squidb/wiki/Unit-testing-with-model-objects

2
Wayne

私は私のプロジェクト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;
    }
}
2
Roger Alien

Robolectricを使用する必要があります。

testImplementation "org.robolectric:robolectric:3.4.2"

その後

@RunWith(RobolectricTestRunner::class)
class TestClass {
    ...
}
2
mac229

ジョニーの答えのフォローアップとして、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;
    });
0
Hylke Bron

解決策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;

    }

}
0
Francis Bacon