0Pricing
Java Academy · บทเรียน

Mockito ขั้นสูง: ตัวจับอาร์กิวเมนต์และสายลับ

จับอาร์กิวเมนต์ของเมธอดด้วย ArgumentCaptor และจำลองออบเจ็กต์จริงบางส่วนด้วย Mockito.spy

Mockito ขั้นสูง: ตัวจับอาร์กิวเมนต์และสายลับ เป็นบทเรียน Java Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Java Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน

ArgumentCaptor: การดักจับอาร์กิวเมนต์ของเมธอด

ArgumentCaptor ดักจับอาร์กิวเมนต์ที่ส่งให้เมธอดจำลอง เพื่อให้คุณตรวจสอบอาร์กิวเมนต์เหล่านั้นได้ มีประโยชน์เมื่ออาร์กิวเมนต์ถูกสร้างขึ้นภายในระบบที่กำลังทดสอบและคุณไม่สามารถเข้าถึงได้โดยตรง

การสร้างและใช้ ArgumentCaptor

สร้างตัวดักจับสำหรับชนิดของอาร์กิวเมนต์ ส่ง captor.capture() เป็นตัวจับคู่อาร์กิวเมนต์ใน verify() จากนั้นเรียก captor.getValue() เพื่อรับอาร์กิวเมนต์ที่ดักจับไว้

@Test
void sends_correct_email() {
    ArgumentCaptor<EmailMessage> captor = ArgumentCaptor.forClass(EmailMessage.class);
    userService.register(new CreateUserRequest("alice@example.com"));
    verify(emailService).send(captor.capture());
    EmailMessage msg = captor.getValue();
    assertEquals("alice@example.com", msg.getTo());
    assertTrue(msg.getSubject().contains("Welcome"));
}

คำอธิบายประกอบ @Captor

ใช้ @Captor ร่วมกับ @ExtendWith(MockitoExtension.class) เพื่อหลีกเลี่ยงการเรียก ArgumentCaptor.forClass() ที่มีรายละเอียดมากเกินไป

@ExtendWith(MockitoExtension.class)
class UserServiceTest {
    @Mock EmailService emailService;
    @Captor ArgumentCaptor<EmailMessage> emailCaptor;
    @Test
    void captures_email() {
        // ...
        verify(emailService).send(emailCaptor.capture());
        assertEquals("Welcome!", emailCaptor.getValue().getSubject());
    }
}

การดักจับการเรียกใช้หลายครั้ง

ใช้ captor.getAllValues() เมื่อเมธอดถูกเรียกหลายครั้ง เมธอดนี้จะส่งคืนรายการค่าที่ดักจับไว้ทั้งหมดตามลำดับการเรียก

verify(emailService, times(3)).send(emailCaptor.capture());
List<EmailMessage> messages = emailCaptor.getAllValues();
assertEquals(3, messages.size());
assertEquals("Confirmation", messages.get(0).getSubject());

Mockito Spies: การจำลองบางส่วน

Mockito.spy() จะห่อหุ้มออบเจ็กต์จริง เมธอดทั้งหมดจะทำงานตามปกติ เว้นแต่คุณจะกำหนดพฤติกรรมจำลองไว้อย่างชัดเจน ใช้เมื่อคุณต้องการทดสอบคลาสที่มีการพึ่งพาบางส่วนซึ่งทดสอบได้ยาก แต่โดยรวมยังทำงานได้ตามปกติ

List<String> realList = new ArrayList<>();
List<String> spy = Mockito.spy(realList);
spy.add("hello"); // calls real ArrayList.add()
System.out.println(spy.size()); // 1 — real method called
doReturn(42).when(spy).size(); // stub just size()
System.out.println(spy.size()); // 42 — stubbed

คำอธิบายประกอบ @Spy

ใช้ @Spy ร่วมกับ @ExtendWith(MockitoExtension.class) เพื่อสร้างสปาย ฟิลด์ต้องได้รับการเริ่มต้นค่า ไม่ว่าจะเริ่มต้นในบรรทัดเดียวกันหรือผ่าน @Spy UserService svc = new UserService(repo);

@ExtendWith(MockitoExtension.class)
class OrderServiceTest {
    @Spy
    OrderService orderService = new OrderService(mockRepo, mockEmail);
}

การสอดส่อง Spring Bean ด้วย @SpyBean

ในการทดสอบ Spring Boot นั้น @SpyBean จะห่อหุ้ม Spring bean ที่มีอยู่ด้วยสปายของ Mockito ซึ่งจะทำงานจริงเว้นแต่จะกำหนดพฤติกรรมจำลองไว้ ใช้คู่กับ @SpringBootTest

@SpringBootTest
class IntegrationTest {
    @SpyBean EmailService emailService;
    @Test
    void order_sends_email() {
        orderService.placeOrder(cart);
        verify(emailService).sendConfirmation(any());
    }
}

doReturn เทียบกับ when().thenReturn() สำหรับสปาย

สำหรับสปาย ให้ใช้ doReturn(value).when(spy).method() แทน when(spy.method()).thenReturn(value) รูปแบบ when(spy.method()) จะเรียกเมธอดจริง ซึ่งอาจทำให้เกิดผลข้างเคียง

// Correct for spies:
doReturn(List.of()).when(spy).findAll();
// WRONG for spies — calls real findAll() first:
when(spy.findAll()).thenReturn(List.of()); // real method called!

การตรวจสอบว่าไม่มีการโต้ตอบ

ใช้ verifyNoInteractions(mock) เพื่อยืนยันว่าออบเจ็กต์จำลองไม่เคยถูกเรียกใช้ และใช้ verifyNoMoreInteractions(mock) หลังจากตรวจสอบการเรียกใช้ที่คาดไว้ทั้งหมดแล้ว เพื่อค้นหาการเรียกใช้ที่ไม่คาดคิด

verifyNoInteractions(emailService); // never called
verify(repo).save(any());
verifyNoMoreInteractions(repo); // save() was the only interaction

การตรวจสอบลำดับด้วย InOrder

ใช้ InOrder เพื่อยืนยันว่าเมธอดของออบเจ็กต์จำลองถูกเรียกตามลำดับที่กำหนด

InOrder inOrder = inOrder(repo, emailService);
inOrder.verify(repo).save(any());
inOrder.verify(emailService).send(any()); // save happened BEFORE send

ตัวจับคู่อาร์กิวเมนต์

ใช้ตัวดักจับร่วมกับตัวจับคู่ ได้แก่ any(), eq(), anyString() และ argThat(predicate) หากอาร์กิวเมนต์ใดใช้อาร์กิวเมนต์ตัวจับคู่ อาร์กิวเมนต์ทั้งหมดต้องใช้ตัวจับคู่ด้วย

verify(repo).save(argThat(user ->
    user.getEmail().endsWith("@example.com") &&
    user.getStatus() == UserStatus.ACTIVE));

ตรวจสอบอย่างรวดเร็ว

เหตุใดจึงควรใช้ doReturn แทน when().thenReturn() เมื่อตั้งค่าพฤติกรรมจำลองของสปาย

สรุป

ArgumentCaptor ดักจับอาร์กิวเมนต์เพื่อให้ตรวจสอบได้หลังการเรียกใช้ สปายจะห่อหุ้มออบเจ็กต์จริงและส่งต่อการทำงาน เว้นแต่จะกำหนดพฤติกรรมจำลองไว้ ใช้ doReturn กับสปาย ใช้ @SpyBean สำหรับการทดสอบการผสานรวมของ Spring ตรวจสอบลำดับการเรียกใช้ด้วย InOrder

คำถามที่พบบ่อย

บทเรียน “Mockito ขั้นสูง: ตัวจับอาร์กิวเมนต์และสายลับ” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “Mockito ขั้นสูง: ตัวจับอาร์กิวเมนต์และสายลับ” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Java Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “Mockito ขั้นสูง: ตัวจับอาร์กิวเมนต์และสายลับ”

จับอาร์กิวเมนต์ของเมธอดด้วย ArgumentCaptor และจำลองออบเจ็กต์จริงบางส่วนด้วย Mockito.spy คุณปฏิบัติ Java Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Java Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Java Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน

บทเรียน “Mockito ขั้นสูง: ตัวจับอาร์กิวเมนต์และสายลับ” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Java Academy นี้ได้ไหม

ได้ บทเรียน Java Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. การทดสอบแบบกำหนดพารามิเตอร์ด้วย @CsvSource และ @MethodSource
  2. Mockito ขั้นสูง: ตัวจับอาร์กิวเมนต์และสายลับ
  3. ส่วนทดสอบ Spring Boot: @WebMvcTest และ @DataJpaTest
  4. Testcontainers: การทดสอบการผสานรวมกับฐานข้อมูลจริง
← กลับไปที่ Java Academy