現在のクラスのプライベート メソッドをモックする方法

背景

基本知識

Mockito 単体テスト: そのアプローチは、現在のクラスのすべての外部依存関係をモックアウトして、独自のコードに問題がないことを確認することです。たとえば、データベース クエリ ステートメントに問題がある場合、単体テストはそれをテストしません。直接モックされるため、実際にはデータベースはチェックされません。この観点から見ると、少し無理が​​あるように思えます。ただし、コードの観点から見ると、何の問題もないようです。その目的は、それ自体のコードが正常であることを確認することであるため、SQL は考慮されません。単体テスト以外にもテストケースもあります。
単体テストを作成するプロセス: 単体テストを作成するときは、コードを 1 行ずつ分析する必要があります。それが外部依存関係である場合は、それをモックし、置き換えとして結果を自分でシミュレートします。それ以外の場合は、コードが終了するまで次の行の分析を続けます。最後に、出力結果が指定された入力で期待どおりであるかどうかを確認します。

現在のクラスのプライベート メソッドをモックする必要があるのはなぜでしょうか?

まず、単体テスト クラスを自動的に生成すると、パブリック メソッドのテスト メソッドのみが作成されます。
ここに画像の説明を挿入します
テスト対象クラスのパブリック メソッドがそのプライベート メソッドを呼び出す場合、単体テストではプライベート メソッドの内容についてモックを 1 行ずつ分析する必要があります。特に、別のパブリック メソッドもこのプライベート メソッドを呼び出す場合、そのパブリック メソッドも同じことを行う必要があります。明らかに、テスト カバレッジの観点から、このプライベート メソッドはカバーされており、行ごとにモックする必要はありません。このとき、このプライベート メソッドをモックできたら素晴らしいですよね。

例えば

テスト対象のクラスを作成する

呼び出されるプライベートメソッドは「リターンあり」と「リターンなし」の2種類に分けられます。リターンを伴うプライベート メソッドを呼び出すために pubFunction1 を作成し、リターンを伴わずにプライベート メソッドを呼び出すために pubFunction2 を作成しました。

package com.aliyu.service.demo.mock;

/**
 * 描述:单元测试如何mock当前类的其他私有方法调用
 * <p>作者: aliyu
 * <p>创建时间: 2023-01-10 10:57 下午
 */
public class MockitoDemo {
    
    

    /**
     * 模拟一个公共方法调用"不带返回"的私有方法
     */
    public void pubFunction1(){
    
    
        System.out.println("开始调用公共方法");
        withoutReturn();
        System.out.println("结束调用公共方法");
    }
    /**
     * 模拟一个公共方法调用"带返回"的私有方法
     */
    public void pubFunction2(){
    
    
        System.out.println("开始调用公共方法");
        withReturn();
        System.out.println("结束调用公共方法");
    }

    private void withoutReturn(){
    
    
        System.out.println("调用了'不带'返回的私有方法");
    }

    private String withReturn(){
    
    
        System.out.println("调用了'带'返回的私有方法");
        return "AAA";
    }
}

テストクラスを作成する

リターンなしのプライベート メソッド モック

ここに画像の説明を挿入します
注: junit4 でなければならないことにも注意してください。そうでない場合は、エラーが報告されます。後述します。
完全なコードは次のとおりです。

package com.aliyu.service.demo.mock;

import org.junit.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

/**
 * 描述:单元测试如何mock当前类的其他私有方法调用
 * <p>作者: aliyu
 * <p>创建时间: 2023-01-11 1:40 上午
 */
@RunWith(PowerMockRunner.class)
@PrepareForTest(MockitoDemo.class)
public class MockitoDemoTest {
    
    

    @InjectMocks
    private MockitoDemo mockitoDemo;

    @BeforeEach
    public void setUp() throws Exception {
    
    
        MockitoAnnotations.initMocks(this);
    }

    /**
     * 测试公共方法调用不带返回的私有方法
     * doNothing实现(暂不清楚和doAnswer的区别,倾向于使用doNothing)
     */
    @Test
    public void testPubFunction1() {
    
    
        MockitoDemo mockitoDemo1 = PowerMockito.spy(mockitoDemo);
        try {
    
    
            PowerMockito.doNothing().when(mockitoDemo1,"withoutReturn");
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
        mockitoDemo1.pubFunction1();
    }

    /**
     * 测试公共方法调用不带返回的私有方法
     * doAnswer实现
     */
    @Test
    public void testPubFunction3() {
    
    
        MockitoDemo mockitoDemo1 = PowerMockito.spy(mockitoDemo);
        try{
    
    
            Answer answer=new Answer(){
    
    
                public Object answer(InvocationOnMock invocationOnMock) throws Throwable{
    
    
                    return null;
                }
            };
            PowerMockito.doAnswer(answer).when(mockitoDemo1,"withoutReturn");
        }catch(Exception e){
    
    
            e.printStackTrace();
        }
        mockitoDemo1.pubFunction1();
    }

}

実行して結果を表示します。
ここに画像の説明を挿入します
注: 「'return' なしで呼び出されたプライベート メソッド」という出力がないことがわかります。これは、モックが成功したことを示しています。

return 付きのプライベート メソッド モック

リターンのないプライベート メソッドとの唯一の違いは、モックに使用されるメソッドです。
ここに画像の説明を挿入します
実行して結果を表示します。
ここに画像の説明を挿入します
注: 「'return' が呼び出されたプライベート メソッド」という出力がないことがわかります。これは、モックが成功したことを示しています。

他の

junit4 の代わりに junit5 を使用すると、エラーが報告されます。ここに画像の説明を挿入します

一般的な意味は、パブリック メソッドには戻り値がなく、戻り値のあるパイルを作成できないということです。明らかに、リターンのあるプライベート メソッドを積み上げています。

戻り値を取得する場合、 doReturn を先頭に置く必要があります。そうしないとモックは失敗します。

ここに画像の説明を挿入します
注: doReturn が戻り値の宣言に失敗した場合、最初にプライベート メソッドが実行されます。

おすすめ

転載: blog.csdn.net/mofsfely2/article/details/128644239