วิธีใช้ Mockito กับ JUnit5


117

ฉันจะใช้การฉีดกับ Mockito และ JUnit 5 ได้อย่างไร?

ใน JUnit4 ฉันสามารถใช้@RunWith(MockitoJUnitRunner.class)Annotation ได้ ใน JUnit5 ไม่มี@RunWithAnnotation?

คำตอบ:


161

มีหลายวิธีในการใช้ Mockito - ฉันจะอธิบายทีละวิธี

ด้วยตนเอง

การสร้าง mocks ด้วยตนเองMockito::mockโดยไม่คำนึงถึงเวอร์ชัน JUnit (หรือกรอบการทดสอบสำหรับเรื่องนั้น)

ตามคำอธิบายประกอบ

ใช้@Mock -annotation และสายที่สอดคล้องกับMockitoAnnotations::initMocks การสร้าง mocksทำงานโดยไม่คำนึงถึงรุ่น JUnit (หรือกรอบทดสอบสำหรับเรื่องที่ แต่ Java 9 อาจรบกวนที่นี่ขึ้นอยู่กับว่ารหัสการทดสอบจะสิ้นสุดลงในโมดูลหรือไม่)

ส่วนขยาย Mockito

JUnit 5 มีรูปแบบการขยายที่มีประสิทธิภาพและ Mockito ตีพิมพ์เมื่อเร็ว ๆ นี้หนึ่งในกลุ่ม / สิ่งประดิษฐ์รหัสorg.mockito : Mockito-junit-ดาวพฤหัสบดี

คุณสามารถใช้ส่วนขยายโดยการเพิ่ม@ExtendWith(MockitoExtension.class)การเรียนการทดสอบและ annotating @Mockเขตเยาะเย้ยด้วย จากMockitoExtensionJavaDoc:

@ExtendWith(MockitoExtension.class)
public class ExampleTest {

    @Mock
    private List list;

    @Test
    public void shouldDoSomething() {
        list.add(100);
    }

}

เอกสาร MockitoExtensionอธิบายถึงวิธีอื่น ๆ ในการสร้างอินสแตนซ์ mocks ตัวอย่างเช่นด้วย constructor injection (หากคุณ rpefer ฟิลด์สุดท้ายในคลาสทดสอบ)

ไม่มีกฎห้ามวิ่ง

กฎ JUnit 4 และนักวิ่งไม่ทำงานใน JUnit 5 ดังนั้นจึงไม่สามารถใช้ตัววิ่งMockitoRuleและMockitoได้


7
ตอนนี้มีส่วนขยาย Mockito Junit5 อย่างเป็นทางการซึ่งเทียบเท่ากับ MockitoJUnitRunner -> mockito-junit-jupiter
dan carter

เมื่อขยายอย่างเป็นทางการสำหรับ Mockito ถูกปล่อยออกมาเขียนบล็อกโพสต์ที่มีรายละเอียดเพิ่มเติมเกี่ยวกับวิธีการกำหนดค่าและใช้: solidsoft.wordpress.com/2018/03/27/...
Marcin Zajączkowski

วิธีการที่ใส่คำอธิบายประกอบ@Testต้องเป็นสาธารณะหรือ "แพ็กเกจส่วนตัว" ดีเพียงพอหรือไม่
Geek

เมื่อเรียกใช้การทดสอบกับดาวพฤหัสบดี (มักเรียกว่า "JUnit 5") วิธีการทดสอบจะต้องมองเห็นได้ในแพ็คเกจเท่านั้น
Nicolai Parlog

63

ใช้ MockitoExtensionMockito ส่วนขยายมีอยู่ในอาร์ติแฟกต์ใหม่mockito-junit-jupiter:

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-junit-jupiter</artifactId>
    <version>2.23.4</version>
    <scope>test</scope>
</dependency>

ช่วยให้คุณสามารถเขียนแบบทดสอบได้ตามที่คุณทำกับ JUnit 4:

import org.mockito.junit.jupiter.MockitoExtension;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;

@ExtendWith(MockitoExtension.class)
class MyTest {

    @Mock
    private Foo foo;

    @InjectMocks
    private Bar bar; // constructor injection

    ...
}

7
@ExtendWith(MockitoExtension.class)เทียบเท่า@RunWith(MockitoJUnitRunner.class)กับ JUnit4
Sergey Nemchinov

ฉันสามารถเรียกเมธอดหลายครั้งที่มีค่าส่งคืนต่างกันบนเมธอดของ Mock object โดยใช้ MockitoExtension.class ใน JUnit5
Raj Hassani

@RajHassani ใช่คุณสามารถดูที่นี่
Jonathan

10

มีหลายวิธีในการทำ แต่วิธีที่สะอาดกว่าและยังเคารพในปรัชญา JUnit 5 คือการสร้าง org.junit.jupiter.api.extension.ExtensionMockito

1) การสร้างล้อเลียนด้วยตนเองทำให้สูญเสียประโยชน์ของการตรวจสอบ Mockito เพิ่มเติมเพื่อให้แน่ใจว่าคุณใช้กรอบงานอย่างถูกต้อง

2) การโทรMockitoAnnotations.initMocks(this)ในทุกชั้นเรียนทดสอบคือรหัสแผ่นหม้อไอน้ำที่เราสามารถหลีกเลี่ยงได้
และการตั้งค่านี้ในคลาสนามธรรมก็ไม่ใช่ทางออกที่ดีเช่นกัน
มันจับคู่การทดสอบทุกคลาสกับคลาสพื้นฐาน
หากคุณต้องการคลาสทดสอบพื้นฐานใหม่ด้วยเหตุผลที่ดีคุณจะจบด้วยลำดับชั้นคลาส 3 ระดับ โปรดหลีกเลี่ยงสิ่งนั้น

3) กฎการทดสอบคือความจำเพาะของ JUnit 4
อย่าแม้แต่คิดว่า
และเอกสารมีความชัดเจนเกี่ยวกับเรื่องนี้:

อย่างไรก็ตามหากคุณตั้งใจจะพัฒนาส่วนขยายใหม่สำหรับ JUnit 5 โปรดใช้โมเดลส่วนขยายใหม่ของ JUnit Jupiter แทนรูปแบบตามกฎของ JUnit 4

4) Test Runner ไม่ใช่วิธีการขยายกรอบ JUnit 5
JUnit 5 ทำให้นรกของ Runners of JUnit 4 ง่ายขึ้นด้วยการจัดเตรียมโมเดลส่วนขยายสำหรับการทดสอบการเขียนด้วย JUnit 5 Extensions
อย่าแม้แต่คิดว่า

ดังนั้นโปรดใช้org.junit.jupiter.api.extension.Extensionวิธีนี้


แก้ไข: จริงๆแล้ว Mockito รวมส่วนขยายของดาวพฤหัสบดี: mockito-junit-jupiter

จากนั้นใช้งานง่ายมาก:

import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
public class FooTest {
     ...    
}

นี่คือคำตอบที่ยอดเยี่ยมของ Jonathan

โดยการเพิ่มการอ้างอิงmockito-junit-jupiterสิ่งประดิษฐ์การใช้@ExtendWith(MockitoExtension.class)ข้อยกเว้นต่อไปนี้ที่สร้างขึ้นเมื่อดำเนินการทดสอบ:

java.lang.NoSuchMethodError: org.junit.platform.commons.support.AnnotationSupport.findAnnotation (Ljava / util / Optional; Ljava / lang / Class;) Ljava / util / Optional;

ปัญหาคือ mockito-junit-jupiterขึ้นอยู่กับไลบรารีอิสระสองแห่ง ตัวอย่างเช่นสำหรับmockito-junit-jupiter:2.19.0:

<dependency>
  <groupId>org.mockito</groupId>
  <artifactId>mockito-core</artifactId>
  <version>2.19.0</version>
  <scope>compile</scope>
</dependency>
<dependency>
  <groupId>org.junit.jupiter</groupId>
  <artifactId>junit-jupiter-api</artifactId>
  <version>5.1.0</version>
  <scope>runtime</scope>
</dependency>

junit-jupiter-api:5.0.1แต่ปัญหาก็คือผมใช้

ดังนั้นในขณะที่การjunit-jupiter-apiเคลื่อนไหวยังคงอยู่บ่อยครั้งในแง่ของ API ตรวจสอบให้แน่ใจว่าคุณใช้เวอร์ชันเดียวกันjunit-jupiter-apiนั้นmockito-junit-jupiterขึ้นอยู่กับ


ทำไมไม่mockito-junit-jupiterดึงเวอร์ชันที่เหมาะสมของjunit-jupiter-api?
haelix

@haelix เนื่องจากกลยุทธ์เวอร์ชันที่ใช้สำหรับการพึ่งพานี้อาศัยไลบรารี Mockito mockito-junit-jupiter:2.19.0ดูรุ่นที่นี่ ในขณะที่ JUnit Jupiter เวอร์ชันเริ่มต้นด้วย5. mockito-junit-jupiter ควรระบุไว้ในสิ่งประดิษฐ์ระบุสองสิ่ง (รุ่น Mockito และรุ่น JUnit Jupiter) เพื่อให้ชัดเจนขึ้น ตัวอย่างเช่นmockito-junit-jupiter-5.1:2.19.0เพื่อสื่อว่าห้องสมุดถูกออกแบบมาสำหรับ JUnit Jupiter 5.1
davidxxx

MockitoExtensionไม่ปรากฏในmockito-coreเวอร์ชัน 3.0.0
Thunderforge

1
@Thunderforge นี้กำหนดไว้ในmockito-junit-jupiter
davidxxx

4

คุณต้องใช้@ExtendWithคำอธิบายประกอบใหม่

น่าเสียดายที่ยังไม่มีการเปิดตัวส่วนขยาย บนgithubคุณจะเห็นการใช้งานเบต้าสำหรับส่วนขยาย เป็นตัวอย่างที่ทดสอบสาธิต

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.