SpringBootでのJPAリポジトリのSaveメソッドのユニットテスト

Aug 22 2020

MockitoとJUnitを使用してこのコードの単体テストを作成する方法を教えてください。StudentRepositoryは、JPAリポジトリを拡張するインターフェースです。

public class StudentService {
    @Autowired
    StudentRepository studentRepository;
    
    public void saveStudentDetails(StudentModel student) {
        Student stud = new Student();
        stud.setStudentId(student.getStudentId());
        stud.setStudentName(student.getStudentName());
        studentRepository.save(stud);
    }
}

回答

3 Borsuk Aug 22 2020 at 00:25

私は数日前に同じ状況にありました、そして私はこのような何かを考えました。

@InjectMocks
StudentService studentService;
@Mock
StudentRepository studentRepository;

public void saveStudentDetailsTest(){
    //given
    StudentModel student = new StudentModel(Your parameters);
    //when
    studentService.saveStudentDetails(student);
    //then
    verify(studentRepository, times(1)).save(any());
}

また、ArgumentCaptorを使用して、保存するために渡すオブジェクトが目的のものであるかどうかを確認できます。これは次のようになります。

ArgumentCaptor<Student> captor = ArgumentCaptor.forClass(Student.class);
verify(studentRepository).save(captor.capture());
assertTrue(captor.getValue().getStudentName().equals(student.getStudentName()));
2 DanielJacob Aug 21 2020 at 23:37

まず、フィールドインジェクションよりもコンストラクターインジェクションを優先します。studentServiceは、studentRepositoryに依存しないと機能しません。変更後は、たとえばMockitoを使用して単体テストを行うことができます。実行する手順:

  1. junit5のExtendsWith(MockitoExtension.class)場合または@RunWith(MockitoJunit4ClassRunner.class)JUnit4の場合のいずれかでクラスに注釈を付けます。
  2. そのタイプの変数に注釈を付けてStudentRepositoryモックを作成します @Mock
  3. サービスの変数に注釈を付けて、モックをサービスに挿入します @InjectMocks
  4. 次に、モックの動作を定義します。構築時にmockitosを使用してこれを行うことができます。それは次のようなものになりますwhen(studentRepository.myMethod()).thenReturn(MyCustomObject())
  5. サービスメソッドを呼び出す
  6. サービスに関する特定の動作を表明します。たとえば、mockitoのverifyコンストラクトを使用しstudentRepository.save()て、一度呼び出されるテストを行うことができます。補足として、保存はvoidを返すのではなく、実際にはエンティティ自体を返す必要があります。
avandeursen Aug 22 2020 at 01:03

あなたのメソッドは2つのことを行うため、テストが難しくなります。

このメソッドは、最初にStudentModelからStudentオブジェクトを作成し、次にStudentオブジェクトを保存します。

2つを分離して、Studentの作成を別のメソッドに抽出できます(サービスに含めることもできますが、StudentクラスまたはStudentModelクラスに含めることもできます)。必要に応じて、そのメソッドを個別に単体テストできます。これにより、ArgumentCaptorを介してこれをテストする必要がなくなります。

これが整ったら、DanielまたはBorsukの回答に従って、サービスが実際にリポジトリのsaveメソッドを呼び出していることを確認できます。