日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

c++返回指针时候注意提防_编写干净的测试–提防魔术

發布時間:2023/12/3 c/c++ 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c++返回指针时候注意提防_编写干净的测试–提防魔术 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

c++返回指針時候注意提防

很難為干凈的代碼找到一個好的定義,因為我們每個人都有自己的單詞clean的定義。 但是,有一個似乎是通用的定義:

簡潔的代碼易于閱讀。

這可能會讓您感到有些驚訝,但我認為該定義也適用于測試代碼。 使測試盡可能具有可讀性是我們的最大利益,因為:

  • 如果我們的測試易于閱讀,那么很容易理解我們的代碼是如何工作的。
  • 如果我們的測試易于閱讀,那么如果測試失敗(不使用調試器),很容易發現問題。

編寫干凈的測試并不難,但是需要大量的實踐,這就是為什么如此多的開發人員為此苦苦掙扎的原因。

我也為此感到掙扎,這就是為什么我決定與您分享我的發現的原因。

這是本教程的第三部分,介紹了如何編寫干凈的測試。 這次,我們將學習兩種可用于從測試中刪除幻數的技術。

救援常量

我們使用在我們的代碼常量,因為沒有常量我們的代碼將與被散落幻數 。 使用幻數有兩個結果:

  • 我們的代碼很難閱讀,因為幻數只是沒有意義的值。
  • 我們的代碼很難維護,因為如果必須更改幻數的值,則必須查找該幻數的所有出現并更新每個幻數。
  • 換一種說法,

    • 常數幫助我們用描述其存在原因的某種事物代替幻數。
    • 常量使我們的代碼更易于維護,因為如果常量的值發生變化,我們只需將該更改僅保留到一個位置即可。

    如果我們考慮從測試案例中找到的幻數,我們會注意到它們可以分為兩組:

  • 與單個測試類相關的幻數。 這種幻數的典型示例是在測試方法中創建的對象的屬性值。 我們應該在測試類中聲明這些常量
  • 與多個測試類別相關的幻數。 這種魔術數字的一個很好的例子是由Spring MVC控制器處理的請求的內容類型。 我們應該將這些常量添加到非實例化類中
  • 讓我們仔細看看這兩種情況。

    在測試類中聲明常量

    那么,為什么我們要在測試類中聲明一些常量呢?

    畢竟,如果我們考慮使用常量的好處,首先想到的是,我們應該通過創建包含測試中使用的常量的類來消除測試中的幻數。 例如,我們可以創建一個TodoConstants類,其中包含TodoControllerTest , TodoCrudServiceTest和TodoTest類中使用的常量。

    這是一個壞主意

    盡管有時候以這種方式共享數據是明智的,但是我們不應該輕易做出這個決定,因為在大多數情況下,我們在測試中引入常數的唯一動機是避免輸入錯誤和幻數。

    另外,如果幻數僅與單個測試類相關,則將這種依賴關系引入我們的測試是沒有道理的,只是因為我們要最大程度地減少創建的常量的數量。

    我認為,處理這種情況的最簡單方法是在測試類中聲明常量。

    讓我們找出如何改進本教程前面部分中描述的單元測試。 編寫該單元測試以測試RepositoryUserService類的registerNewUserAccount()方法,并且當使用社交符號提供者和唯一的電子郵件地址創建新的用戶帳戶時,它驗證此方法是否正常工作。

    該測試用例的源代碼如下所示:

    import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.invocation.InvocationOnMock; import org.mockito.runners.MockitoJUnitRunner; import org.mockito.stubbing.Answer; import org.springframework.security.crypto.password.PasswordEncoder;import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.mockito.Matchers.isA; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when;@RunWith(MockitoJUnitRunner.class) public class RepositoryUserServiceTest {private RepositoryUserService registrationService;@Mockprivate PasswordEncoder passwordEncoder;@Mockprivate UserRepository repository;@Beforepublic void setUp() {registrationService = new RepositoryUserService(passwordEncoder, repository);}@Testpublic void registerNewUserAccount_SocialSignInAndUniqueEmail_ShouldCreateNewUserAccountAndSetSignInProvider() throws DuplicateEmailException {RegistrationForm registration = new RegistrationForm();registration.setEmail("john.smith@gmail.com");registration.setFirstName("John");registration.setLastName("Smith");registration.setSignInProvider(SocialMediaService.TWITTER);when(repository.findByEmail("john.smith@gmail.com")).thenReturn(null);when(repository.save(isA(User.class))).thenAnswer(new Answer<User>() {@Overridepublic User answer(InvocationOnMock invocation) throws Throwable {Object[] arguments = invocation.getArguments();return (User) arguments[0];}});User createdUserAccount = registrationService.registerNewUserAccount(registration);assertEquals("john.smith@gmail.com", createdUserAccount.getEmail());assertEquals("John", createdUserAccount.getFirstName());assertEquals("Smith", createdUserAccount.getLastName());assertEquals(SocialMediaService.TWITTER, createdUserAccount.getSignInProvider());assertEquals(Role.ROLE_USER, createdUserAccount.getRole());assertNull(createdUserAccount.getPassword());verify(repository, times(1)).findByEmail("john.smith@gmail.com");verify(repository, times(1)).save(createdUserAccount);verifyNoMoreInteractions(repository);verifyZeroInteractions(passwordEncoder);} }

    問題在于,此測試用例在創建新的RegistrationForm對象,配置UserRepository模擬的行為,驗證返回的User對象的信息是否正確以及驗證是否調用了UserRepository模擬的正確方法時使用了幻數。在經過測試的服務方法中。

    通過在測試類中聲明常量來刪除這些幻數之后,測試的源代碼如下所示:

    import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.invocation.InvocationOnMock; import org.mockito.runners.MockitoJUnitRunner; import org.mockito.stubbing.Answer; import org.springframework.security.crypto.password.PasswordEncoder;import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.mockito.Matchers.isA; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when;@RunWith(MockitoJUnitRunner.class) public class RepositoryUserServiceTest {private static final String REGISTRATION_EMAIL_ADDRESS = "john.smith@gmail.com";private static final String REGISTRATION_FIRST_NAME = "John";private static final String REGISTRATION_LAST_NAME = "Smith";private static final Role ROLE_REGISTERED_USER = Role.ROLE_USER;private static final SocialMediaService SOCIAL_SIGN_IN_PROVIDER = SocialMediaService.TWITTER;private RepositoryUserService registrationService;@Mockprivate PasswordEncoder passwordEncoder;@Mockprivate UserRepository repository;@Beforepublic void setUp() {registrationService = new RepositoryUserService(passwordEncoder, repository);}@Testpublic void registerNewUserAccount_SocialSignInAndUniqueEmail_ShouldCreateNewUserAccountAndSetSignInProvider() throws DuplicateEmailException {RegistrationForm registration = new RegistrationForm();registration.setEmail(REGISTRATION_EMAIL_ADDRESS);registration.setFirstName(REGISTRATION_FIRST_NAME);registration.setLastName(REGISTRATION_LAST_NAME);registration.setSignInProvider(SOCIAL_SIGN_IN_PROVIDER);when(repository.findByEmail(REGISTRATION_EMAIL_ADDRESS)).thenReturn(null);when(repository.save(isA(User.class))).thenAnswer(new Answer<User>() {@Overridepublic User answer(InvocationOnMock invocation) throws Throwable {Object[] arguments = invocation.getArguments();return (User) arguments[0];}});User createdUserAccount = registrationService.registerNewUserAccount(registration);assertEquals(REGISTRATION_EMAIL_ADDRESS, createdUserAccount.getEmail());assertEquals(REGISTRATION_FIRST_NAME, createdUserAccount.getFirstName());assertEquals(REGISTRATION_LAST_NAME, createdUserAccount.getLastName());assertEquals(SOCIAL_SIGN_IN_PROVIDER, createdUserAccount.getSignInProvider());assertEquals(ROLE_REGISTERED_USER, createdUserAccount.getRole());assertNull(createdUserAccount.getPassword());verify(repository, times(1)).findByEmail(REGISTRATION_EMAIL_ADDRESS);verify(repository, times(1)).save(createdUserAccount);verifyNoMoreInteractions(repository);verifyZeroInteractions(passwordEncoder);} }

    此示例說明在測試類中聲明常量具有三個好處:

  • 我們的測試用例更易于閱讀,因為魔術數字被正確命名的常量所替代。
  • 我們的測試用例更易于維護,因為我們可以更改常量的值而無需對實際測試用例進行任何更改。
  • 為RepositoryUserService類的registerNewUserAccount()方法編寫新測試更加容易,因為我們可以使用常量而不是幻數。 這意味著我們不必擔心拼寫錯誤。
  • 但是,有時我們的測試使用的幻數確實與多個測試類別相關。 讓我們找出如何應對這種情況。

    將常量添加到非實例性類

    如果該常量與多個測試類相關,則在使用該常量的每個測試類中聲明該常量是沒有意義的。 讓我們看一下一種情況,在這種情況下可以向非實例化類添加常量。

    假設我們必須為REST API編寫兩個單元測試:

    • 第一個單元測試確保我們不能向數據庫添加空的待辦事項。
    • 第二個單元測試確保我們不能向數據庫添加空筆記。

    這些單元測試使用Spring MVC測試框架。 如果您不熟悉它,則可能要看一看我的
    Spring MVC測試教程 。

    第一個單元測試的源代碼如下所示:

    import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext;import java.nio.charset.Charset;import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = {WebUnitTestContext.class}) @WebAppConfiguration public class TodoControllerTest {private static final MediaType APPLICATION_JSON_UTF8 = new MediaType(MediaType.APPLICATION_JSON.getType(), MediaType.APPLICATION_JSON.getSubtype(),Charset.forName("utf8"));private MockMvc mockMvc;@Autowiredprivate ObjectMapper objectMapper;@Autowiredprivate WebApplicationContext webAppContext;@Beforepublic void setUp() {mockMvc = MockMvcBuilders.webAppContextSetup(webAppContext).build();}@Testpublic void add_EmptyTodoEntry_ShouldReturnHttpRequestStatusBadRequest() throws Exception {TodoDTO addedTodoEntry = new TodoDTO();mockMvc.perform(post("/api/todo").contentType(APPLICATION_JSON_UTF8).content(objectMapper.writeValueAsBytes(addedTodoEntry))).andExpect(status().isBadRequest());} }

    第二個單元測試的源代碼如下所示:

    import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext;import java.nio.charset.Charset;import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = {WebUnitTestContext.class}) @WebAppConfiguration public class NoteControllerTest {private static final MediaType APPLICATION_JSON_UTF8 = new MediaType(MediaType.APPLICATION_JSON.getType(), MediaType.APPLICATION_JSON.getSubtype(),Charset.forName("utf8"));private MockMvc mockMvc;@Autowiredprivate ObjectMapper objectMapper;@Autowiredprivate WebApplicationContext webAppContext;@Beforepublic void setUp() {mockMvc = MockMvcBuilders.webAppContextSetup(webAppContext).build();}@Testpublic void add_EmptyNote_ShouldReturnHttpRequestStatusBadRequest() throws Exception {NoteDTO addedNote = new NoteDTO();mockMvc.perform(post("/api/note").contentType(APPLICATION_JSON_UTF8).content(objectMapper.writeValueAsBytes(addedNote))).andExpect(status().isBadRequest());} }

    這兩個測試類都聲明一個名為APPLICATION_JSON_UTF8的常量。 該常數指定請求的內容類型和字符集。 同樣,很明顯,在每個測試類中都需要此常量,其中包含用于控制器方法的測試。

    這是否意味著我們應該在每個這樣的測試類中聲明此常量?

    沒有!

    由于以下兩個原因,我們應將此常量移至非實例化類:

  • 它與多個測試類別相關。
  • 將其移到一個單獨的類中可使我們更輕松地為控制器方法編寫新測試并維護現有測試。
  • 讓我們創建一個最終的WebTestConstants類,將APPLICATION_JSON_UTF8常量移動到該類,然后向創建的類添加一個私有構造函數。

    WebTestConstant類的源代碼如下所示:

    import org.springframework.http.MediaType;public final class WebTestConstants {public static final MediaType APPLICATION_JSON_UTF8 = new MediaType(MediaType.APPLICATION_JSON.getType(), MediaType.APPLICATION_JSON.getSubtype(),Charset.forName("utf8"));private WebTestConstants() {} }

    完成此操作后,我們可以從測試類中刪除APPLICATION_JSON_UTF8常量。 我們的新測試的源代碼如下所示:

    import com.fasterxml.jackson.databind.ObjectMapper; import net.petrikainulainen.spring.jooq.config.WebUnitTestContext; import net.petrikainulainen.spring.jooq.todo.dto.TodoDTO; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext;import java.nio.charset.Charset;import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = {WebUnitTestContext.class}) @WebAppConfiguration public class TodoControllerTest {private MockMvc mockMvc;@Autowiredprivate ObjectMapper objectMapper;@Autowiredprivate WebApplicationContext webAppContext;@Beforepublic void setUp() {mockMvc = MockMvcBuilders.webAppContextSetup(webAppContext).build();}@Testpublic void add_EmptyTodoEntry_ShouldReturnHttpRequestStatusBadRequest() throws Exception {TodoDTO addedTodoEntry = new TodoDTO();mockMvc.perform(post("/api/todo").contentType(WebTestConstants.APPLICATION_JSON_UTF8).content(objectMapper.writeValueAsBytes(addedTodoEntry))).andExpect(status().isBadRequest());} }

    我們剛剛從測試類中刪除了重復的代碼,并減少了為控制器編寫新測試所需的工作。 太酷了吧?

    如果我們更改添加到常量類的常量的值,則此更改將影響使用該常量的每個測試用例。 這就是為什么我們應該最小化添加到常量類的常量的數量

    摘要

    現在我們知道,常數可以幫助我們編寫干凈的測試,并減少編寫新測試和維護現有測試所需的工作量。 將本博客文章中給出的建議付諸實踐時,我們需要記住以下幾點:

    • 我們必須給常量和常量類起好名字 。 如果我們不這樣做,就不會利用這些技術的全部潛力。
    • 我們不應該在不弄清楚我們想要用該常數實現什么的情況下引入新常數。 實際情況通常比此博客文章的示例復雜得多。 如果我們在自動駕駛儀上編寫代碼,很可能會錯過針對當前問題的最佳解決方案。

    翻譯自: https://www.javacodegeeks.com/2014/05/writing-clean-tests-beware-of-magic.html

    c++返回指針時候注意提防

    總結

    以上是生活随笔為你收集整理的c++返回指针时候注意提防_编写干净的测试–提防魔术的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。