10

いくつかの静的メソッドを持つ電卓クラスを使用するクラスをテストしようとしています。同様の方法で別のクラスをうまくモックしましたが、これはより頑固であることが証明されています。

モックされたメソッドに渡された引数の 1 つでメソッド呼び出しが含まれている場合、静的メソッドはモックされていないようです (そしてテストが中断されます)。内部呼び出しを削除することは、明らかにオプションではありません。ここで私が見逃している明らかなものはありますか?

これは、同じように動作する圧縮バージョンです...

public class SmallCalculator {

    public static int getLength(String string){

        int length = 0;

        //length = string.length(); // Uncomment this line and the mocking no longer works... 

        return length;
    }
}

そして、ここでテスト...

import static org.junit.Assert.assertEquals;
import static org.mockito.BDDMockito.given;
import static org.mockito.Matchers.any;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import com.solveit.aps.transport.model.impl.SmallCalculator;

@RunWith(PowerMockRunner.class)
@PrepareForTest({ SmallCalculator.class})
public class SmallTester {

    @Test
    public void smallTest(){

        PowerMockito.spy(SmallCalculator.class);
        given(SmallCalculator.getLength(any(String.class))).willReturn(5);

        assertEquals(5, SmallCalculator.getLength(""));
    }
}

質問について混乱があるように思われるので、より「現実的な」例を考案しました。これにより、あるレベルの間接性が追加されるため、モックされたメソッドを直接テストしているようには見えません。SmallCalculator クラスは変更されていません。

public class BigCalculator {

    public int getLength(){

        int length  = SmallCalculator.getLength("random string");

        // ... other logic

        return length;
    }

    public static void main(String... args){

        new BigCalculator();
    }
}

そして、これが新しいテストクラスです...

import static org.junit.Assert.assertEquals;
import static org.mockito.BDDMockito.given;
import static org.mockito.Matchers.any;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import com.solveit.aps.transport.model.impl.BigCalculator;
import com.solveit.aps.transport.model.impl.SmallCalculator;

@RunWith(PowerMockRunner.class)
@PrepareForTest({ SmallCalculator.class})
public class BigTester {

    @Test
    public void bigTest(){

        PowerMockito.spy(SmallCalculator.class);
        given(SmallCalculator.getLength(any(String.class))).willReturn(5);

        BigCalculator bigCalculator = new BigCalculator();
        assertEquals(5, bigCalculator.getLength());
    }
}
4

4 に答える 4

1

まず、その行を削除します。

given(SmallCalculator.getLength(any(String.class))).willReturn(5);

同じ方法をテストしているので。テストしているメソッドをモックしたくありません。

次に、注釈を次のように変更します。

@PrepareForTest({ SmallCalculator.class, String.class})

最後に、length(); のモックを追加します。このような:

given(String.length()).willReturn(5);

私はそれが行うと思います;)

于 2015-07-23T12:52:33.960 に答える
1

anyString()の代わりに使用しany(String.class)ます。

any(String.class)渡された引数 isを使用するとnull、Mockito は参照型のデフォルト値である を返しますnull。その結果、例外が発生します。

を使用するanyString()場合、渡される引数は空の文字列になります。

これは例外が発生する理由を説明していますが、他のコメントや回答で説明されているように、メソッドをテストする方法を確認する必要があります。

于 2015-07-23T12:51:35.197 に答える
0

その実際のメソッドが呼び出されたくない場合。それ以外の

when(myMethodcall()).thenReturn(myResult);

使用する

doReturn(myResult).when(myMethodCall());

それは嘲笑の魔法であり、実際に機能する理由を説明するのは困難です。

他に忘れてたのはmockStatic(SmallCalculator.class)

そして、あなたは必要ありませんPowerMockito.spy(SmallCalculator.class);

于 2015-07-23T13:55:02.263 に答える