Sprgin Testing ‐ Mockito - CCH0124/spring-sandbox GitHub Wiki

啟用 Mockito 註解

  • MockitoJUnitRunner
    • 可以自動初始化所有被 @Mock 注解標記的 Mock 物件
  • MockitoAnnotations.openMocks()
    • 用於手動初始化 Mock 物件,通常在 @BeforeEach 方法中調用
  1. @Mock

可以使用 @Mock 來建立和注入模擬實例,而無需手動建立 Mockito.mock。

  @Mock
  private TutorialRepository tutorialRepository;

    @Test
    void testGetAllTutorials_WhenTitleIsNull() {
        Page<Tutorial> page = new PageImpl<>(List.of(mockTutorial));
        when(tutorialRepository.findAll(any(Pageable.class))).thenReturn(page);

        TutorialResponsePagingDto result = tutorialService.getAllTutorials(null, 0, 10);

        assertEquals(1L, result.totalItems());
        assertEquals(1L, result.totalPages());
        verify(tutorialRepository).findAll(any(Pageable.class));
    }
  1. @DoNotMock

用於指示在測試期間不模擬特定類別。它通常應用於類別或介面(interface)級別。

  1. @Spy @Spy 註解用來創建一個真實物件的代理,同時監控這個物件的所有方法調用。這意味著,當你對一個 @Spy 注解的物件進行測試時,你可以像使用 Mock 物件一樣,驗證它是否被正確地調用,同時又可以保留它原本的行為。

使用時機:

  • 部分模擬: 當希望大部分行為都由真實物件處理,但又想對部分行為進行模擬時
  • 測試繼承: 當測試一個子類,並且希望測試父類的行為時。

@Spy 與 @Mock 的差異

特徵 @Mock @Spy
創建方式 創建一個虛擬的 Mock 物件 創建一個真實物件的代理
行為 所有方法都返回默認值,直到你手動設置 除非你手動設置,否則會調用真實物件的方法
用途 完全隔離單元測試,驗證特定行為 測試真實物件的行為,並在必要時覆寫部分行為
  1. @InjectMocks 使用 @InjectMocks 註解將 @Mock 變數自動注入到被測試物件中。
@ExtendWith(MockitoExtension.class)
class TutorialServiceImpTest {

    @InjectMocks
    private TutorialServiceImp tutorialService;

    @Mock
    private TutorialRepository tutorialRepository;

    @Test
    void testGetTutorialById() {
        when(tutorialRepository.findById(any(UUID.class))).thenReturn(Optional.of(mockTutorial));

        TutorialResponseDto result = tutorialService.getTutorialById(mockTutorial.getId().toString());

        assertEquals(mockTutorial.getTitle(), result.title());
        verify(tutorialRepository).findById(any(UUID.class));
    }
}
@Service
public class TutorialServiceImp implements TutorialService {

  @Autowired TutorialRepository tutorialRepository;

  @Override
  public TutorialResponseDto getTutorialById(String id) {
    return tutorialRepository
        .findById(UUID.fromString(id))
        .map(this::toTutorialResponseDto)
        .orElseThrow(() -> new ResourceNotFoundException("Not found Tutorial with id = " + id));
  }
}

BDDMockito

BDD 鼓勵使用自然的、人類可讀的語言編寫測試,並專注於應用程式的行為。它定義了一種結構清晰的測試編寫方式,分為三個部分 Arrange、Act、Assert:

  • given 前置條件 (Arrange)
  • when 一個動作 (Act)
  • then 驗證輸出 (Assert)
⚠️ **GitHub.com Fallback** ⚠️