成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Mockito 避坑指南 - 常見錯(cuò)誤的預(yù)防與處理

開發(fā) 測(cè)試
在本文中,我們將討論開發(fā)人員在 Spring Boot 應(yīng)用程序中使用 Mockito 框架時(shí)犯的常見錯(cuò)誤,以及代碼示例和解釋。

介紹

Mockito 是一個(gè)流行的用于測(cè)試 Java 應(yīng)用程序的框架。它提供了一種強(qiáng)大且易于使用的方式來模擬依賴關(guān)系和編寫單元測(cè)試。然而,剛接觸 Mockito 的開發(fā)人員可能會(huì)犯一些錯(cuò)誤,從而導(dǎo)致測(cè)試不可靠,甚至導(dǎo)致應(yīng)用程序出現(xiàn)意外行為。在本文中,我們將討論開發(fā)人員在 Spring Boot 應(yīng)用程序中使用 Mockito 框架時(shí)犯的常見錯(cuò)誤,以及代碼示例和解釋。

1.濫用@Mock和@InjectMocks注釋

開發(fā)人員在使用 Mockito 時(shí)最常見的錯(cuò)誤之一是濫用@Mock和@InjectMocks注釋。@Mock注解用于為特定類創(chuàng)建模擬對(duì)象,而@InjectMocks注解用于將模擬對(duì)象注入到被測(cè)試的類中。需要注意的是,@InjectMocks 只能與類一起使用,不能與接口一起使用。

例子:

@RunWith(MockitoJUnitRunner.class)
public class MyServiceTest {
    
    @Mock
    private MyRepository myRepository;
    
    @InjectMocks
    private MyService myService;
    
    // test methods
    
}

2.不重置Mock對(duì)象

Mockito 可創(chuàng)建在多個(gè)測(cè)試中重用的Mock對(duì)象。如果在測(cè)試之間未重置Mock對(duì)象,則可能會(huì)導(dǎo)致意外行為和不可靠的測(cè)試。Mockito 提供了一個(gè)名為Mockito.reset()的方法,可用于重置所有Mock對(duì)象。

例子:

@Before
public void setUp() {
    MockitoAnnotations.initMocks(this);
}

@Test
public void test1() {
    Mockito.when(myRepository.findById(1)).thenReturn(Optional.of(new MyObject()));
    // test code
}

@Test
public void test2() {
    Mockito.when(myRepository.findById(2)).thenReturn(Optional.of(new MyObject()));
    // test code
}

@After
public void tearDown() {
    Mockito.reset(myRepository);
}

3.對(duì)Mock對(duì)象使用錯(cuò)誤的范圍

Mockito 默認(rèn)創(chuàng)建范圍為類級(jí)別。這意味著同一個(gè)Mock對(duì)象將用于類中的所有測(cè)試方法。但是,如果模擬對(duì)象需要為每個(gè)測(cè)試方法具有不同的狀態(tài)或行為,則應(yīng)使用方法級(jí)別的范圍來創(chuàng)建。要?jiǎng)?chuàng)建具有正確范圍的Mock對(duì)象,我們可以使用Spring Boot 提供的@MockBean注解。

@MockBean使用示例:

@RunWith(SpringRunner.class)
@WebMvcTest(UserController.class)
public class UserControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private UserService userService;

    @MockBean
    private UserRepository userRepository;

    @Test
    public void testGetUserById() throws Exception {
        // arrange
        Long userId = 1L;
        User user = new User();
        user.setId(userId);
        user.setName("John Doe");
        Mockito.when(userService.getUserById(userId)).thenReturn(user);

        // act
        MvcResult result = mockMvc.perform(get("/users/{id}", userId))
                .andExpect(status().isOk())
                .andReturn();

        // assert
        String response = result.getResponse().getContentAsString();
        assertThat(response).isEqualTo("{\"id\":1,\"name\":\"John Doe\"}");
        Mockito.verify(userService, times(1)).getUserById(userId);
    }

    @Test
    public void testAddUser() throws Exception {
        // arrange
        User user = new User();
        user.setName("Jane Doe");
        Mockito.when(userService.addUser(user)).thenReturn(user);

        // act
        MvcResult result = mockMvc.perform(post("/users")
                .contentType(MediaType.APPLICATION_JSON)
                .content("{\"name\":\"Jane Doe\"}"))
                .andExpect(status().isOk())
                .andReturn();

        // assert
        String response = result.getResponse().getContentAsString();
        assertThat(response).isEqualTo("{\"id\":null,\"name\":\"Jane Doe\"}");
        Mockito.verify(userService, times(1)).addUser(user);
    }
}

在這個(gè)例子中,我們使用@WebMvcTest注解來測(cè)試UserController類,并注入MockMvc對(duì)象來模擬HTTP請(qǐng)求。我們還使用@MockBean注釋為UserService和UserRepository類創(chuàng)建模擬對(duì)象。

注意,這里不需要在測(cè)試之間重置Mock對(duì)象,因?yàn)锧MockBean注解會(huì)為每個(gè)測(cè)試方法創(chuàng)建Mock對(duì)象的新實(shí)例。

4.不驗(yàn)證Mock對(duì)象

Mockito 提供了 Mockito.verify()的方法,可用于驗(yàn)證是否使用特定參數(shù)調(diào)用了Mock對(duì)象。如果Mock對(duì)象未經(jīng)驗(yàn)證,可能會(huì)導(dǎo)致不可靠的測(cè)試和意外的行為。

Mockito.verify()使用示例:

@RunWith(MockitoJUnitRunner.class)
public class UserServiceTest {

    @Mock
    private UserRepository userRepository;

    @InjectMocks
    private UserService userService;

    @Test
    public void testGetUserById() {
        // arrange
        Long userId = 1L;
        User user = new User();
        user.setId(userId);
        user.setName("John Doe");
        Mockito.when(userRepository.findById(userId)).thenReturn(Optional.of(user));

        // act
        User result = userService.getUserById(userId);

        // assert
        assertThat(result).isEqualTo(user);
        Mockito.verify(userRepository, times(1)).findById(userId);
    }

    @Test
    public void testGetUserByIdNotFound() {
        // arrange
        Long userId = 1L;
        Mockito.when(userRepository.findById(userId)).thenReturn(Optional.empty());

        // act
        UserNotFoundException exception = assertThrows(UserNotFoundException.class, () -> {
            userService.getUserById(userId);
        });

        // assert
        assertThat(exception.getMessage()).isEqualTo("User not found with ID: " + userId);
        Mockito.verify(userRepository, times(1)).findById(userId);
    }
}

請(qǐng)注意,我們使用該Mockito.verify()方法來驗(yàn)證兩個(gè)測(cè)試方法是否使用正確的 ID 并僅調(diào)用了該類的findById()方法一次。使用times(1)參數(shù)來指定該方法應(yīng)該被調(diào)用一次,并傳入正確的 ID 作為參數(shù)。如果未使用正確的 ID 調(diào)用該方法,或者多次調(diào)用該方法,則測(cè)試將失敗。

5.不指定Mock對(duì)象的行為

Mockito 默認(rèn)創(chuàng)建Mock對(duì)象,默認(rèn)行為是“不執(zhí)行任何操作”。這意味著,如果在Mock對(duì)象上調(diào)用方法并且未指定任何行為,則該方法將僅返回 null 或其返回類型的默認(rèn)值。指定Mock對(duì)象的行為來確保它們?cè)跍y(cè)試中按預(yù)期運(yùn)行非常重要。下面是使用Mockito.when()方法指定Mock對(duì)象的行為的示例:

@RunWith(MockitoJUnitRunner.class)
public class UserServiceTest {

    @Mock
    private UserRepository userRepository;

    @InjectMocks
    private UserService userService;

    @Test
    public void testGetAllUsers() {
        // arrange
        List<User> users = Arrays.asList(
                new User(1L, "John Doe"),
                new User(2L, "Jane Doe")
        );
        Mockito.when(userRepository.findAll()).thenReturn(users);

        // act
        List<User> result = userService.getAllUsers();

        // assert
        assertThat(result).isEqualTo(users);
    }

    @Test
    public void testGetAllUsersEmpty() {
        // arrange
        List<User> users = Collections.emptyList();
        Mockito.when(userRepository.findAll()).thenReturn(users);

        // act
        List<User> result = userService.getAllUsers();

        // assert
        assertThat(result).isEqualTo(users);
    }
}

6.使用錯(cuò)誤的方法驗(yàn)證模擬對(duì)象

Mockito 提供了幾種方法來驗(yàn)證是否使用特定參數(shù)調(diào)用了Mock對(duì)象,例如Mockito.verify()、Mockito.verifyZeroInteractions () 和Mockito.verifyNoMoreInteractions () 。使用正確的方法進(jìn)行所需的驗(yàn)證非常重要,因?yàn)槭褂缅e(cuò)誤的方法可能會(huì)導(dǎo)致不可靠的測(cè)試和意外的行為。Mockito.verify()方法使用示例:

@RunWith(MockitoJUnitRunner.class)
public class UserServiceTest {

    @Mock
    private UserRepository userRepository;

    @InjectMocks
    private UserService userService;

    @Test
    public void testGetAllUsers() {
        // arrange
        List<User> users = Arrays.asList(
                new User(1L, "John Doe"),
                new User(2L, "Jane Doe")
        );
        Mockito.when(userRepository.findAll()).thenReturn(users);

        // act
        List<User> result = userService.getAllUsers();

        // assert
        assertThat(result).isEqualTo(users);
        Mockito.verify(userRepository).findAll();
        Mockito.verifyNoMoreInteractions(userRepository);
    }

    @Test
    public void testEmptyUserList() {
        // arrange
        List<User> users = Collections.emptyList();
        Mockito.when(userRepository.findAll()).thenReturn(users);

        // act
        List<User> result = userService.getAllUsers();

        // assert
        assertThat(result).isEqualTo(users);
        Mockito.verify(userRepository).findAll();
        Mockito.verifyNoMoreInteractions(userRepository);
        Mockito.verifyZeroInteractions(userRepository);
    }
}

在第二個(gè)測(cè)試用例中,我們使用Mockito.verifyZeroInteractions()方法來驗(yàn)證測(cè)試期間沒有與Mock對(duì)象發(fā)生交互。這確保只測(cè)試我們想要測(cè)試的行為,并且代碼中不會(huì)發(fā)生意外的交互。

7.不處理異常

以下是使用 Mockito 時(shí)如何處理異常的示例:

@RunWith(MockitoJUnitRunner.class)
public class UserServiceTest {

    @Mock
    private UserRepository userRepository;

    @InjectMocks
    private UserService userService;

    @Test
    public void testGetUserById() {
        // arrange
        Long userId = 1L;
        User user = new User();
        user.setId(userId);
        user.setName("John Doe");
        Mockito.when(userRepository.findById(userId)).thenReturn(Optional.of(user));

        // act
        User result = userService.getUserById(userId);

        // assert
        assertThat(result).isEqualTo(user);
    }

    @Test
    public void testGetUserByIdNotFound() {
        // arrange
        Long userId = 1L;
        Mockito.when(userRepository.findById(userId)).thenReturn(Optional.empty());

        // act and assert
        UserNotFoundException exception = assertThrows(UserNotFoundException.class, () -> {
            userService.getUserById(userId);
        });

        assertThat(exception.getMessage()).isEqualTo("User not found with ID: " + userId);
    }
}

在testGetUserByIdNotFound()方法中,我們Mock UserRepository 類的 findById() 方法以返回一個(gè)空的可選值。然后,我們使用特定 ID 調(diào)用UserService類的getUserById()方法,并且期望該方法拋出UserNotFoundException. 然后使用assertThrows()方法來驗(yàn)證是否拋出了正確的異常,并且我們還使用getMessage()異常的方法來驗(yàn)證是否返回了正確的消息。

8.不使用正確的匹配器

以下是使用 Mockito 時(shí)如何使用正確匹配器的示例:

@RunWith(MockitoJUnitRunner.class)
public class UserServiceTest {

    @Mock
    private UserRepository userRepository;

    @InjectMocks
    private UserService userService;

    @Test
    public void testAddUser() {
        // arrange
        User user = new User();
        user.setName("John Doe");
        user.setAge(30);

        // act
        userService.addUser(user);

        // assert
        ArgumentCaptor<User> captor = ArgumentCaptor.forClass(User.class);
        Mockito.verify(userRepository).save(captor.capture());
        assertThat(captor.getValue().getName()).isEqualTo("John Doe");
        assertThat(captor.getValue().getAge()).isEqualTo(30);
    }
}

使用ArgumentCaptor類來捕獲傳遞給UserRepository類的save()方法的參數(shù)值。我們還使用Mockito.eq()方法來指定方法調(diào)用的參數(shù)值,使用user.getName()和user.getAge()方法來獲取正確的值。這有助于確保向方法傳遞正確的參數(shù),并避免在測(cè)試中出現(xiàn)意外的行為。

下面是另一個(gè)示例:

@RunWith(MockitoJUnitRunner.class)
public class UserServiceTest {

    @Mock
    private UserRepository userRepository;

    @InjectMocks
    private UserService userService;

    @Test
    public void testDeleteUserById() {
        // arrange
        Long userId = 1L;

        // act
        userService.deleteUserById(userId);

        // assert
        Mockito.verify(userRepository, Mockito.times(1)).deleteById(Mockito.eq(userId));
    }
}

使用Mockito.eq()方法來指定deleteById()方法調(diào)用的參數(shù)值。這確保了正確的ID被傳遞給該方法,并避免了測(cè)試中的意外行為。

9.沒有對(duì)Mock對(duì)象使用正確的注解

以下是使用@MockBean 和 @RunWith 注解示例:

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserServiceTest {

    @Autowired
    private UserService userService;

    @MockBean
    private UserRepository userRepository;

    @Test
    public void testGetAllUsers() {
        // arrange
        List<User> users = Arrays.asList(
                new User(1L, "John Doe"),
                new User(2L, "Jane Doe")
        );
        Mockito.when(userRepository.findAll()).thenReturn(users);

        // act
        List<User> result = userService.getAllUsers();

        // assert
        assertThat(result).isEqualTo(users);
    }
}

使用@RunWith和@SpringBootTest注解來配置單元測(cè)試的Spring測(cè)試框架。通過使用這些注解,我們可以確保應(yīng)用程序上下文被加載并且依賴項(xiàng)被正確地注入。

10.未使用正確的測(cè)試配置

我們希望使用正確的配置,以確保正確加載應(yīng)用程序上下文并按預(yù)期注入依賴項(xiàng)。以下是使用@ContextConfiguration 的示例:

@RunWith(MockitoJUnitRunner.class)
@ContextConfiguration(classes = {UserService.class, UserRepository.class})
public class UserServiceTest {

    @Mock
    private UserRepository userRepository;

    @InjectMocks
    private UserService userService;

    @Test
    public void testGetAllUsers() {
        // arrange
        List<User> users = Arrays.asList(
                new User(1L, "John Doe"),
                new User(2L, "Jane Doe")
        );
        Mockito.when(userRepository.findAll()).thenReturn(users);

        // act
        List<User> result = userService.getAllUsers();

        // assert
        assertThat(result).isEqualTo(users);
    }
}

使用@ContextConfiguration注解來指定測(cè)試的配置。我們將一個(gè)類數(shù)組傳遞給它,其中包括UserService和UserRepository類,這樣可以確保它們被加載到應(yīng)用程序上下文中。

11.沒有使用正確的方法來創(chuàng)建Mock對(duì)象

使用正確的方法來創(chuàng)建Mock對(duì)象,以確保依賴項(xiàng)的行為是可控的并且測(cè)試是可靠的。以下是使用Mockito.mock()的示例:

@RunWith(MockitoJUnitRunner.class)
public class UserServiceTest {

    private UserService userService;

    private UserRepository userRepository;

    @Before
    public void setUp() {
        userRepository = Mockito.mock(UserRepository.class);
        userService = new UserService(userRepository);
    }

    @Test
    public void testGetAllUsers() {
        // arrange
        List<User> users = Arrays.asList(
                new User(1L, "John Doe"),
                new User(2L, "Jane Doe")
        );
        Mockito.when(userRepository.findAll()).thenReturn(users);

        // act
        List<User> result = userService.getAllUsers();

        // assert
        assertThat(result).isEqualTo(users);
    }
}

使用了Mockito.when()方法來指定Mock對(duì)象的行為,即當(dāng)findAll()方法被調(diào)用時(shí),返回一個(gè)User對(duì)象的列表。

12.沒有使用正確的方法來存根Mock對(duì)象

使用正確的方法來存根Mock對(duì)象,以確保依賴項(xiàng)的行為可以控制并且測(cè)試是可靠的。以下是使用when().thenReturn()的示例:

@RunWith(MockitoJUnitRunner.class)
public class UserServiceTest {

    @Mock
    private UserRepository userRepository;

    @InjectMocks
    private UserService userService;

    @Test
    public void testGetAllUsers() {
        // arrange
        List<User> users = Arrays.asList(
                new User(1L, "John Doe"),
                new User(2L, "Jane Doe")
        );
        Mockito.when(userRepository.findAll()).thenReturn(users);

        // act
        List<User> result = userService.getAllUsers();

        // assert
        assertThat(result).isEqualTo(users);
    }
}

通過使用Mockito提供的when().thenReturn()方法,我們可以指定模擬對(duì)象的行為并確保在測(cè)試中控制依賴項(xiàng)。

13.沒有使用正確的方法來驗(yàn)證Mock對(duì)象的交互

Mockito 提供了幾種驗(yàn)證 Mock對(duì)象交互的方法,例如Mockito.verify()、Mockito.verifyZeroInteractions()和Mockito.verifyNoMoreInteractions()。使用正確的方法來實(shí)現(xiàn)所需的行為非常重要,因?yàn)槭褂缅e(cuò)誤的方法可能會(huì)導(dǎo)致不可靠的測(cè)試和意外的行為。

@Test
public void test() {
    MyObject myObject = new MyObject();
    myObject.setName("Name");
    Mockito.when(myRepository.findById(1)).thenReturn(Optional.of(myObject));
    
    MyObject result = myService.findById(1);
    
    Mockito.verify(myRepository).findById(1);
    Mockito.verifyNoMoreInteractions(myRepository);
    Assert.assertEquals("Name", result.getName());
}

14.沒有使用正確的方法來驗(yàn)證Mock對(duì)象的交互順序

Mockito 提供了一個(gè)名為Mockito.inOrder()的方法,可用于驗(yàn)證與模擬對(duì)象交互的順序。在驗(yàn)證交互順序時(shí)使用此方法非常重要。

@Test
public void test() {
    MyObject myObject1 = new MyObject();
    myObject1.setName("Name 1");
    MyObject myObject2 = new MyObject();
    myObject2.setName("Name 2");
    InOrder inOrder = Mockito.inOrder(myRepository);
    
    Mockito.when(myRepository.findById(1)).thenReturn(Optional.of(myObject1));
    Mockito.when(myRepository.findById(2)).thenReturn(Optional.of(myObject2));
    
    MyObject result1 = myService.findById(1);
    MyObject result2 = myService.findById(2);
    
    inOrder.verify(myRepository).findById(1);
    inOrder.verify(myRepository).findById(2);
    Assert.assertEquals("Name 1", result1.getName());
    Assert.assertEquals("Name 2", result2.getName());
}

結(jié)論

Mockito 是一個(gè)強(qiáng)大的測(cè)試框架。但是,剛接觸 Mockito 的開發(fā)人員可能會(huì)犯錯(cuò)誤,從而導(dǎo)致應(yīng)用程序中的測(cè)試不可靠和出現(xiàn)意外行為。

責(zé)任編輯:華軒 來源: 今日頭條
相關(guān)推薦

2024-04-03 12:30:00

C++開發(fā)

2019-10-17 09:58:01

深度學(xué)習(xí)編程人工智能

2025-03-26 02:00:00

API工具開發(fā)

2021-02-26 00:46:11

CIO數(shù)據(jù)決策數(shù)字化轉(zhuǎn)型

2024-04-24 13:45:00

2022-01-23 14:29:25

C語言編程語言

2020-12-16 10:00:59

Serverless數(shù)字化云原生

2018-01-20 20:46:33

2022-03-04 18:11:16

信服云

2021-05-07 21:53:44

Python 程序pyinstaller

2023-05-24 10:06:42

多云實(shí)踐避坑

2021-02-22 17:00:31

Service Mes微服務(wù)開發(fā)

2021-05-08 12:30:03

Pythonexe代碼

2025-05-06 08:21:35

2024-08-26 08:29:55

2020-06-12 11:03:22

Python開發(fā)工具

2024-12-31 15:52:43

2021-04-28 09:26:25

公有云DTS工具

2024-07-04 09:05:30

2020-08-26 07:37:25

Nacos微服務(wù)SpringBoot
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 国产精品综合网 | 丁香五月网久久综合 | 久久三级影院 | 亚洲福利电影网 | 欧美11一13sex性hd | 亚洲精品久久久久久久久久久久久 | 久草.com| 在线观看电影av | 日本高清中文字幕 | 香蕉久久久久久 | 国产精品久久久久久影视 | 婷婷在线网站 | 色综合视频 | www.日韩高清 | 午夜视频在线免费观看 | 国产成人综合网 | 久久久2o19精品| 一区二区在线免费观看 | 蜜桃黄网 | 成人污污视频 | 成人免费视频网站在线观看 | 国产精品视频一区二区三区四区国 | 欧美一区二区网站 | 免费中文字幕 | 亚洲一区二区三区免费观看 | 久久99国产精一区二区三区 | 福利片在线观看 | 在线免费观看欧美 | 在线免费观看黄网 | www.久久 | 91精品国产综合久久久久 | 欧美一区不卡 | www.色综合 | 亚洲中午字幕 | 亚洲国产视频一区 | 婷婷色成人| 亚洲一区二区三区在线播放 | av中文字幕在线 | 亚洲色综合 | 国色天香综合网 | 国内毛片毛片毛片毛片 |