เมื่อสร้างการทดสอบและจำลองการอ้างอิงความแตกต่างระหว่างสามแนวทางนี้คืออะไร?
@MockBean:
@MockBean MyService myservice;
@Mock:
@Mock MyService myservice;
Mockito.mock ()
MyService myservice = Mockito.mock(MyService.class);
เมื่อสร้างการทดสอบและจำลองการอ้างอิงความแตกต่างระหว่างสามแนวทางนี้คืออะไร?
@MockBean:
@MockBean
MyService myservice;
@Mock:
@Mock
MyService myservice;
Mockito.mock ()
MyService myservice = Mockito.mock(MyService.class);
คำตอบ:
ห้องสมุด Mockito ธรรมดา
import org.mockito.Mock;
...
@Mock
MyService myservice;
และ
import org.mockito.Mockito;
...
MyService myservice = Mockito.mock(MyService.class);
มาจากไลบรารี Mockito และเทียบเท่ากับฟังก์ชัน
อนุญาตให้ล้อเลียนชั้นเรียนหรืออินเทอร์เฟซและบันทึกและตรวจสอบพฤติกรรมในชั้นเรียน
วิธีการใช้คำอธิบายประกอบสั้นกว่าจึงเป็นที่นิยมและมักเป็นที่ต้องการ
โปรดทราบว่าในการเปิดใช้งานคำอธิบายประกอบ Mockito ระหว่างการดำเนินการทดสอบ
MockitoAnnotations.initMocks(this)
จะต้องมีการเรียกใช้วิธีการแบบคงที่
เพื่อหลีกเลี่ยงผลข้างเคียงระหว่างการทดสอบขอแนะนำให้ทำก่อนการทดสอบแต่ละครั้ง:
@Before
public void initMocks() {
MockitoAnnotations.initMocks(this);
}
อีกวิธีหนึ่งในการเปิดใช้งานคำอธิบายประกอบ Mockito คือการใส่คำอธิบายประกอบในคลาสทดสอบด้วยการ@RunWith
ระบุMockitoJUnitRunner
ว่าทำงานนี้และสิ่งที่มีประโยชน์อื่น ๆ :
@RunWith(org.mockito.runners.MockitoJUnitRunner.class)
public MyClassTest{...}
ห้องสมุด Spring Boot ที่ห่อห้องสมุด Mockito
นี่คือคลาส Spring Boot :
import org.springframework.boot.test.mock.mockito.MockBean;
...
@MockBean
MyService myservice;
ชั้นเรียนรวมอยู่ในspring-boot-test
ห้องสมุด
มันช่วยให้การเพิ่ม mocks Mockito ApplicationContext
ในฤดูใบไม้ผลิ
ถ้า bean ที่เข้ากันได้กับคลาสที่ประกาศมีอยู่ในบริบทมันจะถูกแทนที่ด้วยการจำลอง
หากไม่เป็นเช่นนั้นก็เพิ่มการจำลองในบริบทเป็นถั่ว
อ้างอิง Javadoc:
คำอธิบายประกอบที่สามารถใช้เพื่อเพิ่ม mocks ให้กับ Spring ApplicationContext
...
หากถั่วเดี่ยวที่มีอยู่ชนิดเดียวกันที่กำหนดไว้ในบริบทจะถูกแทนที่ด้วยการจำลองหากไม่มีการกำหนด bean ที่มีอยู่จะมีการเพิ่มถั่วใหม่
เมื่อใช้ Mockito แบบคลาสสิก / ธรรมดาและเมื่อใช้@MockBean
จาก Spring Boot?
การทดสอบหน่วยได้รับการออกแบบมาเพื่อทดสอบส่วนประกอบที่แยกออกจากส่วนประกอบอื่น ๆ และการทดสอบหน่วยก็มีข้อกำหนดเช่นกัน: ให้เร็วที่สุดเท่าที่จะเป็นไปได้ในแง่ของเวลาในการดำเนินการเนื่องจากการทดสอบเหล่านี้อาจดำเนินการในแต่ละวันได้หลายสิบครั้งบนเครื่องของผู้พัฒนา
ดังนั้นนี่คือแนวทางง่ายๆ:
ในขณะที่คุณเขียนการทดสอบที่ไม่ต้องการการอ้างอิงใด ๆ จากคอนเทนเนอร์ Spring Boot Mockito แบบคลาสสิก / ธรรมดาเป็นวิธีที่จะปฏิบัติตาม: รวดเร็วและสนับสนุนการแยกส่วนประกอบที่ทดสอบ
หากการทดสอบของคุณจำเป็นต้องพึ่งพาคอนเทนเนอร์ Spring Boot และคุณต้องการเพิ่มหรือเยาะเย้ยถั่วคอนเทนเนอร์อย่างใดอย่างหนึ่ง: @MockBean
จาก Spring Boot เป็นวิธีการ
การใช้งาน Spring Boot โดยทั่วไป @MockBean
ในขณะที่เราเขียนคลาสทดสอบที่มีคำอธิบายประกอบ@WebMvcTest
(web test slice)
เอกสาร Spring Bootสรุปได้เป็นอย่างดี:
มัก
@WebMvcTest
จะถูก จำกัด ไว้ที่คอนโทรลเลอร์เพียงตัวเดียวและใช้ร่วมกับ@MockBean
เพื่อจัดเตรียมการใช้งานจำลองสำหรับผู้ทำงานร่วมกันที่ต้องการ
นี่คือตัวอย่าง:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@RunWith(SpringRunner.class)
@WebMvcTest(FooController.class)
public class FooControllerTest {
@Autowired
private MockMvc mvc;
@MockBean
private FooService fooServiceMock;
@Test
public void testExample() throws Exception {
Foo mockedFoo = new Foo("one", "two");
Mockito.when(fooServiceMock.get(1))
.thenReturn(mockedFoo);
mvc.perform(get("foos/1")
.accept(MediaType.TEXT_PLAIN))
.andExpect(status().isOk())
.andExpect(content().string("one two"));
}
}
@MockBean
จะแทนที่ bean ในบริบทของแอปพลิเคชันหาก bean ที่ประกาศประเภทเดียวกันถูกกำหนดไว้แล้วในการกำหนดค่า Spring ของคุณ และการฉีดจะดำเนินการในคลาสที่คุณประกาศ @MockBean.
กลไก DI ทำงานในลักษณะนี้: คุณลงทะเบียนอ็อบเจ็กต์ในบริบท DI จากนั้นคุณสามารถฉีดอ็อบเจ็กต์ที่อ้างถึงในบริบท Spring ในคลาสเฉพาะ คุณไม่ฉีดวัตถุในบริบท DI
ในตอนท้ายมันง่ายที่จะอธิบาย หากคุณเพียงแค่ดู javadocs ของคำอธิบายประกอบคุณจะเห็นความแตกต่าง:
@ ม็อก: ( org.mockito.Mock
)
ทำเครื่องหมายฟิลด์เป็นแบบจำลอง
- อนุญาตให้สร้างการจำลองชวเลข
- ลดรหัสการสร้างจำลองซ้ำ ๆ
- ทำให้คลาสทดสอบอ่านง่ายขึ้น
- ทำให้ข้อผิดพลาดในการตรวจสอบอ่านง่ายขึ้นเนื่องจากมีการใช้ชื่อฟิลด์เพื่อระบุการจำลอง
@MockBean: ( org.springframework.boot.test.mock.mockito.MockBean
)
คำอธิบายประกอบที่สามารถใช้เพื่อเพิ่ม mocks ให้กับ Spring ApplicationContext สามารถใช้เป็นคำอธิบายประกอบระดับชั้นเรียนหรือในเขตข้อมูลใน
@Configuration
ชั้นเรียนหรือชั้นเรียนทดสอบที่เป็น@RunWith
SpringRunnerสามารถลงทะเบียน Mocks ได้ตามประเภทหรือชื่อถั่ว ถั่วเดี่ยวที่มีอยู่ประเภทเดียวกันที่กำหนดไว้ในบริบทจะถูกแทนที่ด้วยการจำลองหากไม่มีการกำหนด bean ที่มีอยู่จะมีการเพิ่มถั่วใหม่
เมื่อ
@MockBean
ถูกนำไปใช้ในฟิลด์เช่นเดียวกับการลงทะเบียนในบริบทของแอปพลิเคชันการจำลองจะถูกแทรกลงในฟิลด์ด้วย
Mockito.mock ()
มันเป็นเพียงการแสดงของไฟล์
@Mock
.
@MockBean
และ@Mock
สิ่งที่จะฉีดล้อเลียนเข้าไปในSpring ApplicationContext
และอื่น ๆ จะไม่?