久久亚洲成a人片熟女精品色一区二区三区|国产精品视频第一精品视频|av天堂热无码手机版|亚洲?v无码久久无遮挡|国产精品偷伦视频免费观看国产|麻豆国产自产精品丰满熟妇|av无码av不卡一区二区|久久亚洲精品中文字

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運(yùn)營(yíng)的一線實(shí)戰(zhàn)洞察。

SpringBoot測(cè)試分層實(shí)戰(zhàn):MockMvc到Testcontainers

SpringBoot測(cè)試分層實(shí)戰(zhàn):MockMvc到Testcontainers 要說(shuō)SpringBoot項(xiàng)目里最容易被敷衍對(duì)待的部分測(cè)試絕對(duì)排得上號(hào)。很多人寫(xiě)測(cè)試就是給Service方法加個(gè)Test跑一下發(fā)現(xiàn)綠燈然后就沒(méi)有然后了??傻鹊浇涌诒桓?、數(shù)據(jù)庫(kù)切換、并發(fā)上來(lái)之后最先崩潰的往往就是那堆形同虛設(shè)的測(cè)試。我早年也吃過(guò)這個(gè)虧后來(lái)才慢慢把一個(gè)SpringBoot項(xiàng)目的測(cè)試體系從“會(huì)跑”折騰到“能救命”。這篇文章就把我在實(shí)戰(zhàn)里沉淀下來(lái)的那套打法完整梳理一遍覆蓋從依賴選型、分層策略到MockMvc、Mockito、Testcontainers的落地細(xì)節(jié)以及那些文檔里不會(huì)寫(xiě)的坑。1. 測(cè)試在SpringBoot項(xiàng)目里的定位與分層思路1.1 為什么SpringBoot測(cè)試常?!靶瓮撛O(shè)”很多項(xiàng)目的測(cè)試代碼看起來(lái)不少覆蓋率報(bào)表也好看但一遇到重構(gòu)就稀里嘩啦碎一地。我見(jiàn)過(guò)最常見(jiàn)的病根是把測(cè)試寫(xiě)成了“實(shí)現(xiàn)細(xì)節(jié)的復(fù)讀機(jī)”。比如Service層剛調(diào)了userMapper測(cè)試?yán)锞蚼ock一堆when(userMapper.selectById()).thenReturn(...)然后斷言返回值。一旦把Mapper換成別的數(shù)據(jù)源測(cè)試全部紅掉可業(yè)務(wù)邏輯明明沒(méi)變。這種測(cè)試的問(wèn)題在于它驗(yàn)證的是“代碼是怎么寫(xiě)的”而不是“行為是否正確”。所以我在項(xiàng)目里反復(fù)強(qiáng)調(diào)一個(gè)原則測(cè)試要對(duì)著契約寫(xiě)不要對(duì)著實(shí)現(xiàn)寫(xiě)。接口的輸入輸出、異常規(guī)則、狀態(tài)流轉(zhuǎn)才是契約至于底層用的什么框架、什么ORM都不該是單測(cè)關(guān)心的重點(diǎn)。這個(gè)認(rèn)知不糾正后面所有工具和技術(shù)都是在錯(cuò)誤的路上加速。1.2 測(cè)試金字塔在SpringBoot里的落地方式測(cè)試金字塔這個(gè)概念不新鮮但在SpringBoot里落地時(shí)很多人會(huì)跑偏。理論上應(yīng)該是底層單元測(cè)試最多、中間集成測(cè)試適中、頂層端到端測(cè)試最少??蓪?shí)際上因?yàn)镾pringBoot的SpringBootTest太方便了很多團(tuán)隊(duì)直接把所有測(cè)試都寫(xiě)成全量上下文啟動(dòng)一個(gè)項(xiàng)目跑下來(lái)測(cè)試要十幾分鐘于是大家越來(lái)越不想寫(xiě)測(cè)試。我在實(shí)踐中會(huì)把測(cè)試分成三類來(lái)管控單元測(cè)試針對(duì)Service、工具類、領(lǐng)域?qū)ο蟛粏?dòng)Spring容器用Mockito隔離依賴。切片測(cè)試只加載某一層需要的Bean比如WebMvcTest只加載Controller和MVC相關(guān)配置DataJpaTest只加載Repository和數(shù)據(jù)源相關(guān)配置。集成測(cè)試啟動(dòng)完整上下文必要時(shí)用Testcontainers拉起真實(shí)MySQL、Redis等中間件驗(yàn)證跨模塊交互。這三類的比例我會(huì)控制在7:2:1左右。單元測(cè)試和切片測(cè)試跑得快合并請(qǐng)求時(shí)全量執(zhí)行沒(méi)壓力集成測(cè)試數(shù)量少、價(jià)值高放在發(fā)版流水線里跑。1.3 一套可持續(xù)的測(cè)試策略長(zhǎng)什么樣可持續(xù)的關(guān)鍵不是覆蓋率數(shù)字而是反饋速度和穩(wěn)定性的平衡。我見(jiàn)過(guò)太多測(cè)試綠了但其實(shí)是假綠原因無(wú)非是斷言寫(xiě)得寬松、數(shù)據(jù)沒(méi)清理干凈、隨機(jī)端口沖突等等。所以我會(huì)給項(xiàng)目定幾個(gè)硬規(guī)矩所有測(cè)試必須能重復(fù)執(zhí)行跑十次結(jié)果一致不允許依賴執(zhí)行順序。測(cè)試之間不允許共享可變狀態(tài)數(shù)據(jù)庫(kù)、Redis、文件系統(tǒng)必須在每個(gè)用例結(jié)束后恢復(fù)。單元測(cè)試和切片測(cè)試總耗時(shí)控制在兩分鐘以內(nèi)超過(guò)就要拆分。任何測(cè)試失敗先解決測(cè)試本身不允許用Disabled掩蓋問(wèn)題。這些規(guī)矩剛定的時(shí)候會(huì)有人覺(jué)得麻煩但堅(jiān)持下來(lái)之后測(cè)試是真的敢在發(fā)版前給人信心的。2. 測(cè)試環(huán)境搭建與依賴選型2.1 spring-boot-starter-test里都有什么SpringBoot的測(cè)試依賴非常省心起步就在pom.xml里加一個(gè)spring-boot-starter-testdependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-test/artifactId scopetest/scope /dependency這個(gè)starter做了很多底層整合不是簡(jiǎn)單地把JUnit扔給你。它默認(rèn)帶了一套組合好的測(cè)試工具箱JUnit 5Jupiter現(xiàn)在的基礎(chǔ)測(cè)試框架Test、ParameterizedTest、RepeatedTest都靠它。Spring Test Context提供SpringBootTest、Transactional傳播、TestContextManager等能力。MockitoMock、InjectMocks、when/verify的核心來(lái)源。AssertJ流式斷言庫(kù)assertThat(...).isEqualTo(...)比JUnit原生的assertEquals可讀性好太多。Hamcrest老牌匹配器雖然AssertJ更常用但一些遺留代碼里還會(huì)見(jiàn)到。JSONassert用于對(duì)比JSON結(jié)構(gòu)接口測(cè)試斷言返回體時(shí)很有用。還有個(gè)容易被忽略的是spring-boot-test-autoconfigure所有WebMvcTest、DataJpaTest這類切片注解都來(lái)自它。它保證切片測(cè)試自動(dòng)裝配配置時(shí)不會(huì)誤加載其他層的Bean。需要單獨(dú)補(bǔ)依賴的話一般是加mockito-inline用于mock靜態(tài)方法和Testcontainers相關(guān)的模塊這個(gè)后面細(xì)說(shuō)。2.2 測(cè)試目錄與命名規(guī)范目錄結(jié)構(gòu)直接用Maven/Gradle的標(biāo)準(zhǔn)test目錄就行我習(xí)慣把測(cè)試類按照被測(cè)試類的包結(jié)構(gòu)鏡像并且保持一套統(tǒng)一的命名規(guī)范團(tuán)隊(duì)成員看著不迷路Service層單元測(cè)試UserServiceTestController層切片測(cè)試UserControllerWebMvcTestRepository層切片測(cè)試UserRepositoryDataJpaTest集成測(cè)試UserServiceIntegrationTest命名這件事看起來(lái)細(xì)枝末節(jié)但作用非常大。跑測(cè)試的時(shí)候看到類名就知道它在測(cè)哪一層、需不需要容器環(huán)境排錯(cuò)效率直接翻倍。還有個(gè)小技巧把單元測(cè)試、切片測(cè)試、集成測(cè)試通過(guò)Maven Surefire的groups或命名后綴區(qū)分開(kāi)方便在本地只跑某類測(cè)試。2.3 測(cè)試配置文件的隔離這是非常關(guān)鍵又容易被忽略的一環(huán)。application.yml里往往配置了真實(shí)環(huán)境或開(kāi)發(fā)環(huán)境的數(shù)據(jù)源、緩存、消息隊(duì)列地址測(cè)試如果直接復(fù)用輕則連錯(cuò)庫(kù)重則把測(cè)試數(shù)據(jù)寫(xiě)到生產(chǎn)環(huán)境旁邊的關(guān)系庫(kù)里去。我一般會(huì)建一個(gè)src/test/resources/application.yml用配置覆蓋的方式只保留測(cè)試需要的內(nèi)容spring: datasource: url: jdbc:tc:mysql:8.0.36:///test_db driver-class-name: org.testcontainers.jdbc.ContainerDatabaseDriver jpa: hibernate: ddl-auto: create-drop redis: host: localhost port: 16379注意這里的數(shù)據(jù)庫(kù)地址不是真實(shí)的MySQL地址而是Testcontainers的JDBC驅(qū)動(dòng)地址后面集成測(cè)試部分再展開(kāi)。關(guān)鍵是要理解SpringBoot配置文件加載時(shí)有優(yōu)先級(jí)src/test/resources下的文件優(yōu)先級(jí)高于主目錄下的application.yml這樣測(cè)試項(xiàng)目可以放心覆蓋配置而不用改動(dòng)主代碼的配置。3. 容器測(cè)試與切片測(cè)試怎么選SpringBootTest用前先想清楚3.1 全量上下文啟動(dòng)的利與弊SpringBootTest是SpringBoot測(cè)試?yán)锏摹爸亓考?jí)選手”它的作用是啟動(dòng)完整的Spring容器把幾乎所有的Bean都裝配起來(lái)。好處是貼近真實(shí)運(yùn)行環(huán)境壞處也是顯而易見(jiàn)的啟動(dòng)一次要加載數(shù)據(jù)源、Redis連接、消息隊(duì)列、各種初始化邏輯一個(gè)中型項(xiàng)目跑單個(gè)測(cè)試可能就要十幾秒到幾十秒測(cè)試一多就完全跑不動(dòng)了。我見(jiàn)過(guò)一個(gè)項(xiàng)目光啟動(dòng)容器就要40秒90個(gè)測(cè)試類跑完接近一個(gè)小時(shí)。這個(gè)成本導(dǎo)致開(kāi)發(fā)人員完全不想在本地跑測(cè)試最后測(cè)試形同虛設(shè)。所以我在新項(xiàng)目里對(duì)SpringBootTest的使用非常謹(jǐn)慎只有下面幾種場(chǎng)景才用它跨模塊的端到端業(yè)務(wù)鏈路驗(yàn)證比如從Controller入口一直打到數(shù)據(jù)庫(kù)。配置類的加載驗(yàn)證比如自定義的ConfigurationProperties是否綁定正確。需要完整容器環(huán)境的第三方對(duì)接聯(lián)調(diào)。其他場(chǎng)景能用切片就用切片。這個(gè)觀念轉(zhuǎn)變之后測(cè)試的反饋速度能提升一個(gè)數(shù)量級(jí)。3.2 切片測(cè)試更快但不是萬(wàn)能SpringBoot為每個(gè)常見(jiàn)層次都提供了專門(mén)用于測(cè)試的注解。我這里先列幾個(gè)最常用的切片注解加載范圍典型用途W(wǎng)ebMvcTestController、Filter、ControllerAdvice、MVC配置不加載Service和Repository測(cè)試接口參數(shù)校驗(yàn)、路由映射、返回值結(jié)構(gòu)DataJpaTestRepository、Entity、數(shù)據(jù)源配置默認(rèn)使用內(nèi)嵌數(shù)據(jù)庫(kù)并開(kāi)啟事務(wù)回滾測(cè)試倉(cāng)儲(chǔ)層的CRUD、查詢規(guī)則、分頁(yè)排序JsonTestJackson/Gson的ObjectMapper相關(guān)配置測(cè)試JSON序列化和反序列化規(guī)則RestClientTestRestTemplateBuilder相關(guān)的RestClient配置測(cè)試遠(yuǎn)程HTTP客戶端調(diào)用邏輯MybatisTestMyBatis的Mapper和配置需引入第三方starter測(cè)試MyBatis的SQL語(yǔ)句映射WebMvcTest是我每天都會(huì)用到的。它只加載Web層Service用MockBean新版本里推薦MockitoBean或MockBean具體看Spring版本打樁。這樣啟動(dòng)速度非??煲粋€(gè)Controller相關(guān)的測(cè)試類通常在幾百毫秒內(nèi)就能跑起來(lái)。不過(guò)切片測(cè)試也不是萬(wàn)能藥。WebMvcTest不會(huì)加載你自定義的攔截器之外的全局配置如果攔截器依賴了Service里的數(shù)據(jù)就需要額外把相關(guān)Bean補(bǔ)進(jìn)測(cè)試上下文DataJpaTest默認(rèn)用內(nèi)嵌H2替換真實(shí)數(shù)據(jù)庫(kù)如果項(xiàng)目里用了MySQL特有的JSON字段或全文索引H2大概率模擬不出來(lái)這時(shí)候就得考慮Testcontainers。3.3 不同場(chǎng)景下的選型對(duì)照我在實(shí)際項(xiàng)目中形成了一張很實(shí)用的對(duì)照表每個(gè)新開(kāi)發(fā)者進(jìn)來(lái)我都會(huì)先發(fā)這張表防止他們憑感覺(jué)選測(cè)試方式測(cè)試目標(biāo)推薦方式啟動(dòng)速度真實(shí)度是否要mockController參數(shù)校驗(yàn)、路由WebMvcTest快中mock ServiceService業(yè)務(wù)規(guī)則純JUnit Mockito極快低mock Repository/外部ClientRepository查詢邏輯DataJpaTest較快中取決于數(shù)據(jù)庫(kù)類型不需要跨層主流程SpringBootTestTransactional慢高看情況外部中間件真實(shí)聯(lián)測(cè)SpringBootTest Testcontainers慢極高一般不需要這個(gè)表格背后真正的判斷標(biāo)準(zhǔn)是三個(gè)問(wèn)題測(cè)的是哪一層這層最關(guān)心的風(fēng)險(xiǎn)是什么需要多高的環(huán)境保真度想清楚這三個(gè)問(wèn)題選型就不會(huì)錯(cuò)。4. Controller層測(cè)試實(shí)戰(zhàn)MockMvc的關(guān)鍵細(xì)節(jié)4.1 MockMvc 基本套路Controller層的測(cè)試最常用MockMvc配合WebMvcTest使用不需要真正啟動(dòng)Web容器。直接發(fā)起HTTP請(qǐng)求然后對(duì)返回的響應(yīng)做斷言。下面這段代碼是典型的用法WebMvcTest(UserController.class) class UserControllerWebMvcTest { Autowired private MockMvc mockMvc; MockBean private UserService userService; Test void shouldReturnUserWhenIdExists() throws Exception { UserVO mockUser new UserVO(1L, 張三, zhangsanexample.com); given(userService.findById(1L)).willReturn(mockUser); mockMvc.perform(get(/api/users/1) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath($.name).value(張三)) .andExpect(jsonPath($.email).value(zhangsanexample.com)); } }given是Mockito BDD風(fēng)格的寫(xiě)法等價(jià)于when(...).thenReturn(...)只是可讀性更好。很多人寫(xiě)Controller測(cè)試時(shí)習(xí)慣直接調(diào)Controller的方法這樣其實(shí)繞過(guò)了路由解析、參數(shù)綁定、序列化這些真正的風(fēng)險(xiǎn)點(diǎn)測(cè)試價(jià)值大打折扣。用MockMvc走一趟完整請(qǐng)求鏈路才檔得住真實(shí)的調(diào)用問(wèn)題。4.2 斷言比調(diào)用更重要測(cè)試的核心不是把請(qǐng)求發(fā)出去而是做足夠嚴(yán)謹(jǐn)?shù)臄嘌?。我?jiàn)過(guò)不少同事寫(xiě)完andExpect(status().isOk())就收工了根本沒(méi)驗(yàn)證返回內(nèi)容。這種測(cè)試跟沒(méi)寫(xiě)差不多接口里面隨便改點(diǎn)東西都會(huì)照常綠。我給團(tuán)隊(duì)定的標(biāo)準(zhǔn)是至少覆蓋狀態(tài)碼status().isOk()、isCreated()、isBadRequest()等。業(yè)務(wù)字段用jsonPath逐一斷言核心字段不允許只斷一個(gè)$.code。關(guān)鍵時(shí)序涉及異步或重定向時(shí)檢查響應(yīng)頭里的Location或狀態(tài)流轉(zhuǎn)。異常路徑參數(shù)缺失、資源不存在、權(quán)限不足每一種都得有對(duì)應(yīng)的用例。JSONPath斷言是接口測(cè)試?yán)锏睦?。假設(shè)返回體是{data: {items: [{id: 2}, {id: 5}]}}可以這樣寫(xiě).andExpect(jsonPath($.data.items.length()).value(2)) .andExpect(jsonPath($.data.items[1].id).value(5))注意length()這個(gè)函數(shù)式寫(xiě)法很多人在第一次接觸JSONPath時(shí)會(huì)漏掉導(dǎo)致斷言怎么寫(xiě)都不對(duì)。4.3 常見(jiàn)翻車點(diǎn)我在接口測(cè)試?yán)锊冗^(guò)不少坑挑幾個(gè)典型分享MockBean的返回值類型不一致如果UserService.findById返回的是OptionalUserVO但代碼里處理的是null判斷mock時(shí)容易返回Optional.empty()而忘掉對(duì)應(yīng)邏輯分支然后測(cè)試通過(guò)的代碼拿真實(shí)數(shù)據(jù)就出問(wèn)題。建議mock時(shí)先確認(rèn)生產(chǎn)代碼的判空路徑。日期時(shí)間格式LocalDateTime默認(rèn)序列化格式是數(shù)組比如[2025, 5, 1, 10, 30, 0]。如果接口要對(duì)前端返回yyyy-MM-dd HH:mm:ssController測(cè)試?yán)锉仨汄?yàn)證這個(gè)格式否則到聯(lián)調(diào)時(shí)才暴露就晚了。分頁(yè)參數(shù)的默認(rèn)值Spring Data的分頁(yè)接口如果沒(méi)傳page和size會(huì)走默認(rèn)值。測(cè)試?yán)锶绻粶y(cè)默認(rèn)值后面前端傳錯(cuò)參數(shù)也沒(méi)人發(fā)現(xiàn)。靜態(tài)資源處理WebMvcTest默認(rèn)不會(huì)加載靜態(tài)資源映射如果Controller里有重定向到靜態(tài)頁(yè)面的接口測(cè)試?yán)锟梢酝ㄟ^(guò)手動(dòng)添加資源處理器或者改用SpringBootTest。還有一點(diǎn)很多人不知道MockMvc的perform其實(shí)會(huì)在內(nèi)部走完整的DispatcherServlet所以Valid注解觸發(fā)的參數(shù)校驗(yàn)在WebMvcTest里是真實(shí)生效的。換句話說(shuō)Controller層的參數(shù)校驗(yàn)測(cè)試完全可以在切片環(huán)境里做不需要跑到集成測(cè)試?yán)镌傺a(bǔ)。5. Service層單元測(cè)試Mockito的正確姿勢(shì)5.1 基礎(chǔ)三件套Service層是業(yè)務(wù)邏輯的聚集地測(cè)試價(jià)值最大但也是最容易被寫(xiě)壞的。我常用的基礎(chǔ)模式是MockInjectMocksExtendWith(MockitoExtension.class) class UserServiceTest { Mock private UserRepository userRepository; Mock private PasswordEncoder passwordEncoder; InjectMocks private UserService userService; Test void shouldCreateUserWithEncodedPassword() { String rawPassword abc12345; given(passwordEncoder.encode(rawPassword)).willReturn(encoded-value); User created userService.createUser(zhangsan, rawPassword); assertThat(created.getPassword()).isEqualTo(encoded-value); verify(userRepository).save(any(User.class)); } }ExtendWith(MockitoExtension.class)是JUnit 5與Mockito集成的入口沒(méi)有它Mock和InjectMocks不會(huì)生效。InjectMocks會(huì)優(yōu)先按構(gòu)造器注入其次是setter和字段注入這要求被測(cè)類的依賴盡量通過(guò)構(gòu)造器聲明否則容易注入不進(jìn)去。5.2 別mock一切很多人寫(xiě)Service測(cè)試時(shí)有個(gè)壞毛病把Service內(nèi)部依賴的私有方法也通過(guò)mock去繞開(kāi)。實(shí)際上Mock只能作用于類的公開(kāi)協(xié)作對(duì)象私有邏輯該測(cè)還是得測(cè)。更糟糕的是有些人會(huì)把UserRepository.save(...)的返回值mock成一個(gè)帶ID的復(fù)雜對(duì)象結(jié)果Service里后續(xù)依賴的字段沒(méi)設(shè)置測(cè)試和真實(shí)行為對(duì)不上。我踩過(guò)一次最深的坑是某個(gè)下單流程里OrderRepository.save()返回的訂單對(duì)象里有個(gè)凍結(jié)金額字段我mock的時(shí)候忘了set值導(dǎo)致后續(xù)計(jì)算一直為0測(cè)試卻綠了。上線后真實(shí)數(shù)據(jù)一跑就出狀況。那之后我定了個(gè)規(guī)則能少mock就少mock能走真實(shí)對(duì)象就走真實(shí)對(duì)象。Repository里的方法如果有清晰的返回規(guī)則我寧愿寫(xiě)個(gè)真實(shí)的實(shí)體對(duì)象傳進(jìn)去也不想mock出個(gè)殘缺對(duì)象。另外verify經(jīng)常被用錯(cuò)。verify(userRepository).save(...)驗(yàn)證的是這個(gè)調(diào)用發(fā)生過(guò)一次但如果你想要的是“最終調(diào)用了兩次”這種次數(shù)斷言需要配合times(2)。不要濫用verifyNoMoreInteractions()它會(huì)把測(cè)試綁死在實(shí)現(xiàn)細(xì)節(jié)上。5.3 靜態(tài)方法與構(gòu)造方法Mockito的老版本不支持mock靜態(tài)方法SpringBoot新版本里如果項(xiàng)目引用了mockito-inline就可以搞定try (MockedStaticIdGenerator mocked mockStatic(IdGenerator.class)) { mocked.when(() - IdGenerator.nextId()).thenReturn(42L); // 執(zhí)行被測(cè)代碼 }mockStatic返回的對(duì)象要記得關(guān)閉否則會(huì)影響同進(jìn)程里其他測(cè)試。一般用try-with-resources包住即可。對(duì)new出來(lái)的對(duì)象可以用mockConstruction但這兩個(gè)功能我建議盡量少用。遇到靜態(tài)方法調(diào)用優(yōu)先考慮通過(guò)注入接口來(lái)消除靜態(tài)依賴而不是依賴Mockito的擴(kuò)展能力。因?yàn)殪o態(tài)mock一旦用多測(cè)試會(huì)變得非常隱晦出問(wèn)題也難排查。6. 真實(shí)數(shù)據(jù)庫(kù)聯(lián)測(cè)從H2到Testcontainers6.1 H2的甜蜜與陷阱DataJpaTest默認(rèn)會(huì)用H2代替真實(shí)數(shù)據(jù)庫(kù)如果項(xiàng)目用的是Hibernate大部分CRUD能正常跑通??梢坏┥狭薓ySQL的方言特性H2就會(huì)開(kāi)始背叛你。我在項(xiàng)目里遇到的典型問(wèn)題包括H2對(duì)JSON類型的支持是模擬的序列化/反序列化行為跟MySQL不一致。MySQL的ON DUPLICATE KEY UPDATE在H2里是另一套語(yǔ)法。分頁(yè)查詢的LIMIT ? OFFSET ?表現(xiàn)有差異。字段默認(rèn)值、字符集排序規(guī)則不同可能導(dǎo)致測(cè)試通過(guò)但線上失敗。所以我的經(jīng)驗(yàn)是H2只適合驗(yàn)證查詢邏輯的雛形凡是涉及數(shù)據(jù)庫(kù)特性的項(xiàng)目真正該做的是用Testcontainers跑真實(shí)數(shù)據(jù)庫(kù)。6.2 Testcontainers 落地方式Testcontainers是一個(gè)極其好用的庫(kù)它能在測(cè)試時(shí)用Docker臨時(shí)拉起容器測(cè)試結(jié)束自動(dòng)銷毀保證環(huán)境干凈。SpringBoot生態(tài)里甚至有專門(mén)為它準(zhǔn)備的starterdependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-testcontainers/artifactId scopetest/scope /dependency有了這個(gè)依賴測(cè)試?yán)锟梢赃@樣用Testcontainers class UserRepositoryDataJpaTest { Container static MySQLContainer? mysql new MySQLContainer(mysql:8.0.36) .withDatabaseName(test_db) .withUsername(test) .withPassword(test); // 通過(guò)動(dòng)態(tài)屬性注冊(cè)把數(shù)據(jù)源地址指到容器 DynamicPropertySource static void configureDatasource(DynamicPropertyRegistry registry) { registry.add(spring.datasource.url, mysql::getJdbcUrl); registry.add(spring.datasource.username, mysql::getUsername); registry.add(spring.datasource.password, mysql::getPassword); } }Container標(biāo)注的靜態(tài)字段只啟動(dòng)一次所有測(cè)試類共享同一套數(shù)據(jù)庫(kù)容器速度還能接受。DynamicPropertySource用來(lái)動(dòng)態(tài)注入配置比寫(xiě)死application.yml里的連接地址要靈活得多。更省事的寫(xiě)法是直接用JDBC URL里的tc:前綴這樣連Container都不用單獨(dú)聲明spring: datasource: url: jdbc:tc:mysql:8.0.36:///test_db driver-class-name: org.testcontainers.jdbc.ContainerDatabaseDriver這種玩法會(huì)自動(dòng)按URL拉起容器對(duì)已有代碼改動(dòng)最小。我最近幾個(gè)新項(xiàng)目都用的這個(gè)方式唯一需要保證的是CI機(jī)器上有可用的Docker環(huán)境。6.3 事務(wù)回滾與數(shù)據(jù)污染數(shù)據(jù)庫(kù)測(cè)試最大的敵人是數(shù)據(jù)污染。Spring對(duì)測(cè)試方法上有Transactional的方法是會(huì)默認(rèn)回滾的DataJpaTest本身也自帶這個(gè)行為。但如果測(cè)試?yán)镉玫氖荢pringBootTest想回滾就得自己加Transactional或者借助BeforeEach清理數(shù)據(jù)。我得提醒一個(gè)容易踩的坑測(cè)試方法里有異步操作或者數(shù)據(jù)庫(kù)操作發(fā)生在獨(dú)立線程時(shí)事務(wù)回滾會(huì)失效。比如Service里用了Async測(cè)試方法結(jié)束后異步線程還在寫(xiě)數(shù)據(jù)回滾根本攔不住它。這也是為什么異步邏輯的測(cè)試要用真實(shí)數(shù)據(jù)庫(kù)加顯式清理或者用Mockito把異步邏輯改成同步執(zhí)行具體要看業(yè)務(wù)場(chǎng)景。另外Testcontainers容器雖然會(huì)銷毀但它拉起容器可能要花十幾秒。如果測(cè)試類特別多容器資源會(huì)互相占用。我建議給CI機(jī)器配置足夠的Docker資源或通過(guò)compose.yml的方式復(fù)用一套容器不要每個(gè)測(cè)試類都另起一個(gè)MySQL實(shí)例。7. 測(cè)試執(zhí)行效率與CI集成7.1 上下文緩存Spring的TestContext框架默認(rèn)會(huì)緩存應(yīng)用上下文只要配置相同多個(gè)測(cè)試類可以復(fù)用同一個(gè)上下文。這對(duì)性能影響巨大因?yàn)橐粋€(gè)全量SpringBootTest上下文可能耗時(shí)幾十秒復(fù)用后多個(gè)測(cè)試類共享一次啟動(dòng)成本。但緩存有幾個(gè)失效因素要特別注意MockBean或新版本的MockitoBean改變了上下文的定義用了不同mock的測(cè)試類會(huì)各自創(chuàng)建一根上下文。DynamicPropertySource會(huì)作為緩存key的一部分每個(gè)測(cè)試類如果注入不同的屬性緩存也失效。ContextConfiguration中的locations或initializers不同同樣會(huì)產(chǎn)生新上下文。所以在寫(xiě)測(cè)試時(shí)我會(huì)盡量讓同一批測(cè)試的配置保持一致尤其是切片測(cè)試中聲明mock的方式不要一會(huì)兒一變。7.2 隨機(jī)測(cè)試帶來(lái)的確定性接口測(cè)試?yán)镒钆碌氖请S機(jī)性。比如測(cè)試依賴某個(gè)ID主鍵自增跑過(guò)一次后數(shù)據(jù)變了第二次執(zhí)行就失敗。解決辦法是不要讓測(cè)試依賴任何來(lái)自外部環(huán)境的可變值??梢杂霉潭〝?shù)據(jù)、顯式清理、或者在斷言前先重置數(shù)據(jù)庫(kù)狀態(tài)。DirtiesContext這個(gè)注解我一般很謹(jǐn)慎地用。它會(huì)讓測(cè)試結(jié)束之后銷毀上下文下次再創(chuàng)建一個(gè)新的。這個(gè)成本非常高通常只在測(cè)試會(huì)修改Bean狀態(tài)、影響后續(xù)測(cè)試時(shí)才需要。如果是為了解決數(shù)據(jù)污染就上DirtiesContext那是用大炮打蚊子會(huì)導(dǎo)致整個(gè)測(cè)試套件變得奇慢無(wú)比。7.3 CI里怎么跑測(cè)試在CI里的運(yùn)行策略和本地不完全一樣。我一般把Maven Surefire配置成默認(rèn)跑所有單元測(cè)試和切片測(cè)試集成測(cè)試另用failsafe插件單獨(dú)跑放在發(fā)版管道里plugin groupIdorg.apache.maven.plugins/groupId artifactIdmaven-surefire-plugin/artifactId version3.2.5/version configuration includes include**/*Test.java/include include**/*WebMvcTest.java/include include**/*DataJpaTest.java/include /includes excludes exclude**/*IntegrationTest.java/exclude /excludes /configuration /plugin對(duì)應(yīng)地集成測(cè)試類命名為XxxIntegrationTest交給failsafe插件去跑。這樣本地可以快速跑完單元測(cè)試CI的合并請(qǐng)求階段也不會(huì)被重量級(jí)集成測(cè)試拖慢。CI環(huán)境里還常見(jiàn)一個(gè)問(wèn)題測(cè)試偶發(fā)失敗。偶發(fā)失敗比穩(wěn)定失敗更折磨人常見(jiàn)來(lái)源是端口沖突、外部服務(wù)超時(shí)、并發(fā)測(cè)試爭(zhēng)搶資源。我強(qiáng)烈建議把Surefire配置成parallel時(shí)只對(duì)無(wú)狀態(tài)的純單元測(cè)試開(kāi)啟并行涉及容器或數(shù)據(jù)庫(kù)的測(cè)試不要并行否則排查成本比省下來(lái)的時(shí)間還高。8. 常見(jiàn)問(wèn)題排查速查表最后整理一張我這些年攢下來(lái)的排查表基本上項(xiàng)目里踩過(guò)的測(cè)試坑都在這了。遇到問(wèn)題先對(duì)著這張表查一遍很多坑可以直接跳過(guò)。現(xiàn)象常見(jiàn)原因處理方式SpringBootTest啟動(dòng)失敗報(bào)數(shù)據(jù)源URL為空測(cè)試配置沒(méi)有正確覆蓋主配置確認(rèn)src/test/resources/application.yml存在且數(shù)據(jù)源配置完整測(cè)試方法內(nèi)開(kāi)了事務(wù)但數(shù)據(jù)沒(méi)有被回滾方法里啟動(dòng)了新線程或調(diào)用了Async改用真實(shí)數(shù)據(jù)庫(kù)顯式清理或mock掉異步邏輯MockMvc測(cè)試報(bào)404WebMvcTest沒(méi)有包含目標(biāo)Controller在注解里顯式列出WebMvcTest(UserController.class)Mockito報(bào)UnnecessaryStubbingException打樁沒(méi)有被用到刪除多余的given(...)或使用lenient()Testcontainers起不來(lái)提示連接Docker失敗CI機(jī)器沒(méi)有Docker或Docker版本不兼容確保Docker daemon存活檢查測(cè)試機(jī)的socket權(quán)限D(zhuǎn)ataJpaTest中SQL語(yǔ)法錯(cuò)誤H2與MySQL方言不一致如果涉及數(shù)據(jù)庫(kù)特性切換Testcontainers真實(shí)數(shù)據(jù)庫(kù)測(cè)試之間數(shù)據(jù)相互污染沒(méi)有清理數(shù)據(jù)或事務(wù)回滾失效在每個(gè)用例前清理目標(biāo)數(shù)據(jù)表或使用Transactional保證回滾jsonPath($.data).value(...)一直失敗返回體結(jié)構(gòu)與預(yù)期不一致先用andReturn().getResponse().getContentAsString()打印返回體再比對(duì)測(cè)試上下文緩存未生效每次都重啟MockBean或DynamicPropertySource使用不一致導(dǎo)致緩存key變化盡量統(tǒng)一同一批測(cè)試類的mock聲明和配置注入排查時(shí)有個(gè)非常實(shí)用的招式別急著改代碼先看測(cè)試失敗時(shí)的完整日志和返回體。MockMvc測(cè)試失敗時(shí)經(jīng)常會(huì)打印完整的響應(yīng)內(nèi)容很多人忽略了這行輸出直接去翻生產(chǎn)代碼浪費(fèi)大量時(shí)間。我個(gè)人在實(shí)際操作中的體會(huì)是SpringBoot測(cè)試這事的核心并不在于會(huì)用幾個(gè)注解而在于建立起“分層驗(yàn)證、快慢分離、持續(xù)可跑”的測(cè)試?yán)砟睢淖畛醯腟pringBootTest一把梭到現(xiàn)在每層各司其職項(xiàng)目的回歸速度和質(zhì)量穩(wěn)定性都有了根本性的變化。這個(gè)內(nèi)容后續(xù)還可以繼續(xù)擴(kuò)展成一套團(tuán)隊(duì)內(nèi)部的測(cè)試規(guī)范文檔把切片選型、命名規(guī)范、容器管理、CI流水線配置都沉淀成模板讓每個(gè)新加入項(xiàng)目的同事都能少踩我踩過(guò)的那幾年坑。
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
青草园大香蕉| 中国一级αV| 在线观看精品国产免费| 蜜臀久久99精品久久久久| 成人熟女区| 国产欧美一区激情交| 东北少妇高潮zzzz| 亚洲骚逼少妇| 精品美女人人干| 人妻精品综合中文字幕在线 | 韩国黄片aaaa| 日韩啊V| 操逼999| 六六久久日韩不卡| 日本在线不卡123| 日韩一级成人毛片免费观看 | 久草免费在线一区二区| 人人看人人插| 91被操| 热热色91| 97爱爱爱| 99无码狠狠久久| 国产后入式在线观看| 久久国产精品,久久国产| 免费综合亚洲中文| 国产精品一级片在线看| 69精品久久久久中文字幕| 国产性爱在线视频一区二区| 激情小说在线视频| 97操| 色色色日本| 久久男人的天堂| www.91视频网| 亚洲色婷婷综合久久久久中文| 99只有精品| 欧美综合色站| 亚洲色91C| 99色悠悠| 人妻美腿丝袜制服诱惑综合天堂-| 一品道视频一区二区三区| 九九Av| 久草福利在线资源站| 日韩 欧美 视频 在线 一区| 人人操人人操人人人操| 日韩不卡在线一区二区| 国产精品无码AV网站| 浪人综合网| 久久精品中文字幕无码l| 亚洲无无码αⅴ每日更新| 很很操在线| 乱伦色图网址是多少| 91丨国产丨白浆秘 洗澡动漫| 欧美天天弄| 天天综合91| 国产偷拍网站| 无码高清国产AV| 免费A V在线| 这里都是精品在线观看| 人妻熟女一区在| 又黄又爽在线观看视频| 国产夜夜艹| 色香在线| 少妇久久久久久| 欧美成人A√在线一区二区| 操逼免费视频无码国产| 成人网址在线观看| 久久精品欧美一区蜜桃| 超碰97亚洲区| 亚洲欧洲激情卡通另类文学四射小说网站| 97视频在线观看免费高清| 97视频一区| 26uuu久久| 国产自产一区视频在线| 久久97| 熟女AV一区| 91精品婷婷国产综合久久| 99re在线| 婷婷丁香五月天综合东京热| 日本999精品视频| 欧美天天综合站| 99精品无码| J?P?NESEHD熟女熟妇伦| 韩国午夜理伦三级好看| 久久久婷| 欧美激情视频一区二区| 人妻 丝袜美腿 中文字幕| 国产精品免费美女视频| av天天在线| 91n处女在线观看| 新久久AV| 青青草字幕AV| 中文乱码字字幕在线第5页| 国产精品久久久无码AV网站| 亚洲熟妇极品| 91亚洲综合| 黄色一区二区秘书性感| 欧美日本久久精品一区 | www.亚洲黄色| 久久人妻四季| 精品999一区二区| 超碰国产精品久| 青草青青久久久久久国产| 精品妇操一区二区三区| 国产精品爱欲| 亚洲综合码| 日韩日本欧美在线观看| 国产原创自拍| 三及片网站| 亚欧日韩成人| 亚洲欧美一区二区不卡视频播放| 2023天天操夜夜操| 亚洲色欲一区二区三区| 国产强奸乱伦无码视频| 精品大久久| 丝袜足交视频| 天天日天天操心| 热久久无毒不卡| 东北丰满熟女国产一区| 欧美熟女妇同| 日本国产欧美高清在线| 97爱啪| 国产精品久久久无码AV网站| 好吊爽好吊爽在线视频,中文字幕精品一区二区日本,国产良妇出轨视频在线观看, | 爽极品影院| 蜜奶av| 国产无码久久高清| AV99热18这里只有精品| www.99中文字幕| 91nbbbbbb| 国产日韩色综合| 亚洲色图a| 操屄日韩| 一直超碰| 无码 有码 国产18p| 亚洲综合贴图91| 影视综合无码少妇| 日日骚精品视频| 亚欧日韩成人| 欧美乱欲| 国产一区二区三区不卡手机在线| 亚洲精品自拍| 亚洲和欧美裸体美女双飞视频| 激情小说图片亚洲首页| 撸撸成人在线视频| 久久激情五月| 84YTCOM性无码| 亚洲欧美setu| 97摸视频| 91亚洲欧洲| 男人天堂站| 久久伊人亚洲AV无码网站| 老鸭窝黄色视频网站| 大香蕉黄色一级片免费看| 精品久久九| 色五月激情网| 黄色人人| 亚欧美综合网| 欧美视频激情久久久久久| 啪啪视频mP4| 精品人成视频在线观看| 天天干夜夜| 大香蕉97久久| 亚洲欧美精品福利在线| 国产在线视频二区| 欧美日韩中文字幕不卡| 欧美在线55555| 丁香婷婷九月| 无码 黑人一区二区三区| 99草精| 成人贴图日韩欧美| 五月天婷婷基地| 国产JDAV无码视频在线观看| 国产丝袜一区二区三区| 欧美天天谢综合网| 五月婷婷爱六月丁香色| 成人自拍三级在线观看| 日日不卡av| 欧色综合| 日韩电影天堂视频一区二区| 青娱乐导航AV| 青青11操操操操操操操操| 欧美黄色片在线播放| 超碰97资源网亚洲| 大鸡巴久久| 亚州综合色图| surenchaopeng| 久久精品人体AV| 操逼网站视频漫画国产| 丰满人妻一区二区三区性色| 欧美性性性| 人妻素股| 久9爱经典视频| 97精品综合久久网| 日韩精品人妻中文字幕有码午| 小情侣高清国产在线视频| 欧美传媒| 青草成人免费视频一com| 玖色av| 色天欧美| 足交视频老司机| 丝袜无码a片| 又大又黄国产| 青青操97| 色噜噜国产在线| 91oumei| 丁香五月av| 亚洲欧美一区二区三区一猛片| 免费1级a做爰片观看| 91啦人妻| 午夜乱轮操逼视频免费看| 可以看的av| 日本午夜久久电影| 久久久婷| 精品一区二区三区蜜桃臀赵总 | 亚洲一区中文精品| 中日韩熟女| 国产一区自拍欧美日韩| 精品视频免费在线一区| 九九性爱网| 99操视频| 懂色AV一区二区三区| 超碰 97国产熟女| 67194无码不卡| 18一区二区三区| 91麻豆天美国产| 亚州中文字幕超碰97| 国产天美传媒精品| 欧美色老汉| 酒色综合网| 91日韩| 亚洲 自拍偷拍 欧美| 成人三一级一片aaa| 久久久久国产精品喷潮免费观看臀 | 日韩人妻 中文字幕| 亚洲αv一区二区三区| 图片区小说区| www.狠狠干.coom | 日韩综合97p| 曰韩中文人妻视频| 免费自拍三级综合| 99色色网| 澳门成人网站久国产日韩| 国产精品经典一卡久久久 | 青春草A| 小明看看网址| 久久9精品| 91狠狠综合| 91高潮| 91在线精品一区二区三区| 欧美v亚洲v综合v国产v妖精| 在线综合色| 色色色999| 97国产超湿| 免费人人搞97| 久艹视频在线| 神马久久久久久久| 天天干,天天日| 综合网久久| 国产精品午夜福利视频| 青娱乐久久艹| 九九av| 97久精品| 亚洲黄色电影| 亚洲国产婷婷在线播放| 亚洲,欧美,春色,另类| 超碰97男人| 啊啊啊啊,啊啊好多水| 欧美一区二区男人天堂| 性爱1区| 操逼精品视频| 日本不卡二区| 欧美在线播放aaaa| 四虎免费看黄| 99精品国产户外露出| 久久国内| 亚州日韩97| 国产一区二区在线播放| 色色色欧美| 国产精品麻豆成人AV艾秋| 97草草| 人妻一区二区三区四区视频| 久久久人体| 国产麻豆一区二三区| 欧美激情综合网| 天天干夜夜操网| 加勒比AV网| 一区二区不卡视| 成人免费在线网站| 超碰夫妻97| 久久久无码视频| 人妻中文字幕精品无码 | 伊人97| 欧美日韩国产黄色片| 亚洲综合影片| 大象AV在线| 九九在线视频| 91亚洲欧美激情| 天天日天天干天天整| 国产丰满熟夫69mpp| 免费岛国一级片| 91亚·色| 亚洲影院365| 精精夜夜| 国产三级资源在线观看| 国产传媒美日韩av| 欧美日本中字另类在线| 免费看国产大AB| 国产精品点击进入在线影院| 婷婷大香蕉| 国产精品播放| 国产成人亚洲精品自产在线| 久久精品国产亚洲av水密被窝| 三级三级三级a级全黄三| 欧美大片一区二区三区 | 婷婷在线视频| 91av一区二区在线观看| 久久久18禁| 激情抓乳插进去啪啪啪日韩 | 久久久久久久久久久久久久久久9| 一级乱伦网站| 综合天天网| 不卡av在线中文字幕| 青青草视频导航官网| 日韩在线欧美精品一区二区| 碰超人人在线一区二区三区| 青娱乐国产精品| 91国产伊人大香蕉| 婷婷五月色| 99久久99久久免费精品蜜臀| 91精品国产综合久久久蜜臀| 男人的天堂 在线一区| 啊啊啊不要啊啊受不了了视频在线 | 欧洲精品欧洲精品| 国产日韩欧美三级片 | 日本中文字幕在线视频| 在线综合网| 国产精品久久久久久久久久久久久久久久 | 啊啊啊好大好湿| 欧美精品日韩久久久九| 欧美日韩小说| 九一综合精品视品av| 天天激情综合站| 九九超碰综合网| 成片免费播放| 国产精品人妻无码久久久互動交流| 欧美一二三区四五区| av在线观看不卡网站| 四虎影视 亚洲无码| 青青11操操操操操操操操| 亚洲日本激情| 屁股久久久久久久| 欧美春色| 不卡一区视频| ,国产乱人伦精品一区二区三区| 一区二区三区在线美女| 大香蕉伊人网| 天天综合网亚洲综合网| ′ !γ}丶。。久久精品欧美一区二区三区 | 色欧洲| 日本999精品| 亚洲成人av色网| 欧美日韩国产高清在线一二三区| 久久久精品网站| 中文字幕精品专区搜索结果91| 天天射,天天操,天天爽-国内精品一区二区三区-成人AV | 嫩呦国产一区二区三区AV| 日韩丨制服丨中文|在线| 久久精品小视频| 熟女色综合久久| 亚洲伊人久久综合97| www.久久超碰| 涩亚洲欧洲| 欧美综合在线91| 91超碰人人| 99啪啪视频| 亚洲精品性爱片| 中文字幕精品一区二| 亚洲欧美999| 日本二区不卡| 色婷婷A V一二三四区麻豆综合| 熟妇亚洲一区二区三区| 精品十三区| 91久久精品国产| 亚洲色久| 色99在线| 91爱综合| 啊啊啊啊啊啊啊好爽不要| 欧美九九爱| 99色视频| 9九九九九视频在线观看| 久久肏大逼| 国产福利av精彩对白| 无码人妻精品一区二区中文| 久久首页| 久操网视频| 伊人久久综合影院| 99ri在线视频| AV大香蕉| 江都AV在线| 激情图片亚洲色图| 激情综合av| 嫩草 我啊~嗯~在线| 情色五月天网| 天天射夜夜| 国产婷婷综合在线观看| 欧美+日产+中文| 亚洲色91| 韩国一级婬片A片无码天美| 思思热在线视频免费| 98人妻精品一区二区色欲| 精品国产Av无码久久久伦古装| 岛国黄片网站| 日韩卡一卡二卡三在线| 国产情侣自拍在线播放| 亚洲成人久久美女| 日日狠狠久久偷偷色综合免费| 黄页大片在线观看| 久久鲁夜| 色路综合| 9丨亚洲一区二区在线| 成 人片 黄色大片| 香蕉在线一区二区三区| 麻豆AV一区二区| 日韩中文字幕2020| 欧美色图20P| 久久人妻熟女一区二区| 日韩激情无码影院| 亚洲免费人妻在| 亚洲 日韩 欧美 国产综合体| 夜夜一区二区| 天天情欲宗合网| 婷婷五月天激情四射| A级片日韩欧美国产欧美视频精选观看| 亚洲AV色图| 家庭乱伦麻豆| 国产欧美精选自拍一区| 97啪啪| 国内黄色精品| 日日躁狠狠躁天天躁精品| 精品国产a∨一区天美传媒| 亚洲欧美日韩免费观看| 3P乱轮视频| 91久久国产综合久久| 大香蕉宅男伊人| 欧美色图亚洲激情| 午夜精品久久久久久久99蜜桃一| 最新AVzaixian| 成人欧美日超碰| 男人的天堂2019| 色999亚洲人成色| 欧美少妇性乱| 亚洲无码偷拍| 日日干夜夜干| 大乔未久88一区| A级片一区| 色狠狠综合| 97爱b| 97干97色| 99久视频| 超碰 欧美| 欧美一区二区三区互相| 97色伦欧美| 97操97干| 九色婷婷| julia国产在线| 中国大陆国产高清AⅤ毛片| 在线99热| 后入综合久久| 久久五月天婷婷丁香中文字幕| 高凊专区人人操| 99少妇内射| 99国产精品久久久在线播放| 97综合久久| 玖玖视频在线资源一区二区三区| 国产sv美女内射| 1禁看欧美黄片免费看| 一区| 太久视频| 久草电影网| 欧美强奸乱| 亚洲美女自拍偷拍视频| 久久久久国产| 黄色网址在线免费观看| 亚洲日韩欧美一区二区| 2017人人操,人人摸| 欧美香蕉视xxx| 亚洲影院成人| 国产女人极品高潮毛片| 老司机免费视频在线91| 八人操人人摸人人看| 宅男午夜在线视频| 国产一区二区三区,在线观看观看| 亚洲麻豆av一区二区| 亚洲日本男人天堂网| 精品三级在线专区| 久久草视频污视频| 丰满少妇乱子伦精品无| 视频二区美腿制服人妻欧美| 成人看片网站| 色啪网| 国产熟妇 码视频户外直播| 天堂av2019| 色在线综合| 黄色高清无码无码破解免费暗网| 久久激情视频| 成人婷婷丁香| 伊人丁香五月婷婷| 在线天堂999| 岛国黄片网站| 操逼无毒无码免费视频| 狠狠干狠狠色| 亚洲一卡二卡在线免费| 日韩欧美资源| 久久久久久久少妇| 国产野战露脸在线播放| 日韩无码服务区| 国产11页| 欧美操逼熟女| 2017天天拍大香蕉| 2017大香蕉国产精品久久| 激情啪啪拍91| 一级成人性爱| 97chaopenrihan| 国产精品久久久亚洲一区| 2018天天日天天日| 蜜桃天美传媒AV一区二区三区| 黄色AV影视| 精品人妻中文字幕4399| 少妇无码999| 日韩精品9区| 日韩精品99999| 免费人成在线观看网站品爱网| 国产精品午夜福利| 大奶尤物鲍汁淫荡欧美视频粉嫩夜夜骚| 日语五十路和六十路亚洲国产精品 | 97超级久久强资源| 黄色AAAAAAAAAAA大片| 欧美性综合| 欧美性爱97超碰| 亚洲精品中文字幕一区在线视频| 人妻色偷色噜| 久久久久成人网| 97一区二区三区视频| 18一区二区三区| 337p大胆噜噜噜噜噜91Av| 东京热视频网| 岛国爱情动作片在国产AV无码专区亚洲AV漫画| 天天碰操中国年青熟妇| 屌逼麻豆| 大香蕉九九| 中文字幕精品一区二区精| 97超碰欧美| 99re在线视频国产| 97超碰亚洲| 国产无马av| 看一级特黄a大一片| 伊人操你| 中文三一区| 亚洲,欧美,综合网| 九一性生活免费视频| 天堂麻豆天美| 中文字幕55555| AV天天在线观看| 丁香五月天激情| 曰韩成人免费视频| 岛国视频免费在线观看| 精品欧美А∨无码黑人大荫蒂 | 久久男人的天堂| 久久久无码视频| 97se亚洲综合自| 亚洲中文字幕av| av影院十区| 啊嗯嗯啊好大好爽| 日日日啊啊啊| 亚洲成人精品久久久| 欧美最婬乱婬爆婬性视频 | 伊色综合天堂色97| 欧美色图天堂在线| 加勒比无码一区二区三区| 婷婷五月天丁香| 五月色丁香| 正在播放:深夜激情大战,自带黑丝袜全力输出骚穴 | 校园激情狠狠四射| 校园春色五月天| 超碰九7| 明星性猛交ⅹxxx乱大交| 久久加勒比| 亚欧毛片基地国产毛片基地| 午夜无遮挡男女啪啪视频| 超碰国产精品久| 久久久国产亚洲精品系列| 嫖老熟女A片一二三区| 亚洲成熟国产精品美女| 国产AV久久久蜜爱影集| 很很干很很操| 91少妇香蕉久久精品| 老女人老91妇女老热女| 亚洲欧美天| 日韩成年人性爱视频| 亚洲激情在线观看一区| 色综合久久88色综合久久天天| 黄片aaaaa一区| 婷婷六月色| 欧美狠狠操| 天天影视之亚洲综合网| 超碰九区| 熟女字幕| 久久综合日韩亚洲欧美| 麻豆传媒一区二区在线观看| 婷婷激情四射| 伊人久久在线视频观看| 六月丁香久久| 男人天堂日日夜夜| 国产极品馒头逼| 手机在线中文字幕国产| 欧美性特| 国产情色在线| 懂色Av| 国产色呦呦| 熟妇人妻一区二区三区| 久久国产视频专区一二三 | 激情无码日韩| 欧州色图区| 亚洲天堂一二| 国产传媒午夜理伦精品| 色一情一乱一乱一区91Av| 日韩懂色网| 久久久91| wwwcaobibi| 操操操操操操| 国产无码三级视频在线观看| www.99视频| 中文一区在线日| 大JI巴好深好爽又大又粗视频| 国内自拍 日韩激情 99| 裸模AV女优| 色吧91| 六月婷婷综合| 抽插一区二区视频| 国产成人亚洲精品无码古代早漏男| 丰满人妻-区二区三区免费| 91女优在线观看 | 伊人久久国产免费观看视频| 婷婷20月天青娱乐| 国产亚洲精品美女久久久m| 综合网欧| 中文?日韩?免费?精品| 中文字幕在线免费观看视频| 亚热日本熟女| 黑人猛交| 天天欧美色| 亚洲九九九九| 91欧美高清| 97日亚洲欧美| 99热精品在线播放| 日1区2区3区2020| 性爱av在线免费观看| 天天日美女的B| 久久社区一区二区三区| 伊人国产视频| 综合五月婷婷亚洲一区| 欧美 熟女 日韩| 8x福利精品第一福利视频导航| 宅男午夜在线视频| 91熟女在线| 五月丁香综合| 夜夜爽夜夜爽| 刺激性视频黄页| 国产精品露脸在线观看| 久草在| 日韩Va亚洲va欧美Ⅴa久久| 九九国产热| 操逼视频亚洲| 久热网| 一区二区影院| 亚洲熟女一区二区| 日本在线激情一区二区三区 | 色色色色日本| 蜜桃精品一区二区三区久在线| 岛国在线一区二区三区| 亚洲一本色码中文字幕| 国产亲戚伦亲在线| 精品国产乱码久久久影院| 天天干天天拍| 日日操免费视频| 亚欧美综合网。| 日本一区二区做爱的视频| 日韩本不卡视频在线观看| 狠狠狠狠狠| 99久久亚洲精品无码毛片潘甜甜| 日韩精品99久久久久久中文字幕| 操逼片中文| 欧日韩在线观看| 爱射综合| 国产精品免费1区2区视频| 国产少妇高潮| 五月综合视频| www.99色| 99最新日韩偷拍视频| 中国一区二区亚洲人妻| 97 色综合| 动漫av中文| 黄色小视频日本txt| 97se亚洲综合自| 亚洲天堂男人在线| 国产精品女生av| 亚洲欧美激情小说| 99热导航| 这里有精品| 玖玖爱免费观看视频| juliaann欧美丝袜办公室| 久久一区,青青青青草视频在线播放| 男人在线天堂| 久久久内射良家| 老鸭窝亚洲毛片| 国产精品免费视频人成| 黑人白女精品一区| 黄色成年| 天天拍天| 欧美色997| 精品久热| 99久久e免费热视| 人人爱人人乐人人操| 久9综合在线| 色九九九综合| 丝袜综合| 不卡超碰护士AV在线免费播放| 影音先锋少妇| 清纯唯美亚洲| 東南亚性呦成人伦理资源在线视频| 青青草视频导航官网| 国产精品香蕉热久久新品| 国产精品日日摸夜夜添骚逼| 国产夫妻性生活视频| caopeng97人妻| 欧美日日网| 久久九九99| 久久久久亚洲Aⅴ无码| 秋霞一集毛片观看| 九九久久玖玖| 78操B| 蜜臀久久99精品久久久久久婷婷| 久久亚州大香蕉| 欧美午夜色妇色鬼| 亚洲色图超碰在线| 视频二区美腿丝袜制服人妻欧美| 国产在线视视频有精品| 中文一区在线视频| 日本天天操| 色色香蕉| 乱伦熟女区| 亚洲综合婷婷| 日本中文字幕在线电影| 欧美中出1| 中文字幕一区二区在线日韩精品| 一级人妻性爱视频| 日韩欧美操逼xxx| 日本性爱视频一级| 国产无码三级视频在线观看| 人人做,人人操,人人摸| 亚洲啪啪视频免费| 级做a爱无码性色永久免费| 情趣丝袜无码操逼视频| 超碰国产精品无码| 欧美大香蕉同搞| 日韩探花精品在线视频| 中日韩欧美精品无码AⅤ一区二区| 91搞逼视频| 萌白酱自拍视频| 色欲日韩欧美在线一区| 成人性爱视频在线看| 国产高清MV操逼视频| 性在久久久久久| 国产九九九九九九九九| 青娱乐日韩无码| 九九久久精品| 91久精品| 黄色污污污污污污网站| 4141514逼喷水三级片| 久久少妇人妻| 精品人妻一区二区三区视频在线| 男人天堂毛片| 色欲av国内精品久久久久久| av一区二区三区不卡| 自怕偷自怕亚洲精品| 日韩不卡在线一区二区| 欧美性爱五月天| 日韩内射视频| 欧美性生活内射| 这里都是精品| 日本不卡高清视频| 97人人草| 日韩精品9999| 99热线麻豆 | 九九九九精| 八戒午夜福利理论片| 在线人人人人人人精品超| 3d成人精品一区二区| www.久久爱| 九九成人精品| 你草精品在线视频| 狠久久| 日韩精品人妻| 天天插天天操| 九九热超碰97亚洲最新香蕉| 日韩成人人妻网站| 91五十路| 国产九九九九九九九九| 久久9亚洲| 青青草视频导航官网| 白 大 人妻 区 在线| 91狠狠综合久久久| 久久久18| 激情文学网伊人| 伊人青青草久久| 96久久久久久久| 日韩啪啪啪啪啪| 日本免费一区二区不卡| 国产99热| 日韩AV熟女乱伦| 国产精品91ai| 麻豆国产97在线| 六月色色| 超碰吊日色| 伦伦成年午夜免费视频| 艳美熟妇先锋一二三区| 男人天堂毛片| 综合欧美日本三级| 久操网在线| 亚洲一区二区三区播放在线| 国产精品白虎| 久一区久久蜜桃| 性爱1区| 青操影院| 免费一级a毛片久久久久久鸭绿欲| 国产精品久久久久久夜夜夜| 国产风韵犹存熟妇三区| 欧美人妻久久精品二区三区| 校园春色亚洲欧洲| 99久久99久久免费精品蜜臀| 日韩啪啪网| 久久大香蕉97| 九九色图| 亚洲熟女综合网| 六月丁香网| 国产综合久| 久99热| 亚洲 在线| 久久极品伊人| 黄色成人网久久久久久| 亚洲色堂免费视频| 2017,超碰| 人妻AV在线| 91美女视频在线观看| 五月天婷婷成人网| 中文有码9| 亚洲黄色影视| 欧美男人天堂| 99精品在线观看| 极品另类| 久久久久9久久久久| 国产一国产一级毛片古装| 不卡码视频| 6080YYY午夜理论片在线观看| 内射黑人| 神马久久久久久伦理片| 亚洲91射| 亚洲 日本 一 二 三| 日本熟妇浓毛hdsex| 久久中日麻豆| 国产精品干干干| 中出91视频| 九九十八精品| 最新三级网址| 欧美碰碰综合色| 久极品在线观看| 国产精品盗摄 偷窥盗摄| 亚洲区限制级| 99无码精品| 绯色一区二区三区不卡少妇| 成人久久久精品| 久久婷综合| 欧美极品美女aaaaaa级黄片| 91激情网| 激激五月| 少妇无码av专区线| 天天干夜夜鈤| yazhousetuoumei| 亚洲成人日韩小说| 男人天堂新| 精品一区二区三区四区外站| 欧美性爱精品一区二区| 欧美性爱18观看| 国产风韵犹存熟妇三区| 夜夜操狠狠操| 日本成人电影资源网| 熟妇女伦乱视频| 日韩午夜国产| 狠狠干婷婷| 熟女乱伦A| 天操天操夜操夜月月年年操操| 久久精品人体AV| 播播亚洲小说亚洲| 综合网久久| 91 手机在线播放 绯色| 久久亚洲精品成人av| 日韩欧美亚洲自拍偷拍| 日本天堂在线播放| 9超碰免费| 小草三级久久观看| 人、人、摸,人、人、草| .精品人妻一区二区三| 老司机香蕉| 国产五码丝袜屁眼| 九九精品美女高溯喷水| 婷婷久久综合| 操逼视频亚洲| WWW操逼| 91AV入口| 美女性91| 欧美亚洲特P| 亚洲偷91色| 亚欧中文字幕在线视频| 日韩欧美视频青青| 女人爽到高潮潮喷18禁网站| 日韩在线观看三级电影| 日韩本不卡视频在线观看| 大屁股国产在线视频| 宗合情欲网| 亚洲欧美精品一区天堂久久| 色婷婷在线视频| 免费看久久久性性| 久久直播国产| 国产精品一区av在线| 国产 亚洲 一二三四| 粉嫩av在线| 99婷婷一区二区| 欧美色亚洲| 日韩九九九| 久久精品国产99久久,亚洲日韩久久日本一区一区三区 | 日韩欧无码一区二区三区免费不卡| 嗯嗯啊啊啊好爽| 老汉网| 欧美色图成人网一区二区 | 五月天激情小说| 亚洲精品乱码久久久久久蜜桃麻豆 | 国产亚洲深夜激情| 在线中文字幕| 很很操在线| a级免费在线观看| 国产又色又粗又黄又爽| 亚洲黄片免费在线播放| 国产一区二区二区按摩精品啪视频| 国产免费内射视频| 亚洲97| 久久久久久9| 欧美成人性活片| 国产精品不卡一区二区三区av| 97色碰| 久久的免费性爱视频| 午夜福利国产欧美日韩夜夜| 日韩操逼HD| 久久中文字幕不卡人妻| 国产一级高跟丝袜| 国产视频一区二区免费| 国产尹人在线视频免费| 日韩免费性爱视频在线观看| 久99久视频| 免费看污网站| 色嘟嘟人妻天堂网| 91激情网| 色欲天香天天综合网-成年人三级片网站-欧美乱妇狂野-日韩国产专区-久久久久久 | 亚洲熟妇AV日韩熟妇在线| 青青草色AV| 欧美高清第一页| 东北丰满熟女国产一区| 911粉嫩人妻| 精品久久久av| 玖玖综合.com| 加勒比日本在线| 999国产精品999久久久久久| 亚洲日韩精品一区二区| 中文字幕一二区二三区人妻专区| 国产尤物AV尤物在线观看不卡| 99色热| 国产91精品久久久久久久网曝门| 人妻内射一区二区在线视频| 98久久超碰| 国产亚洲福利第一页丝袜| 国产92麻豆天美精品色欲5| 国产毛片精品一区二区色欲黄A片| 超碰成人最新最好看| 丝袜熟女2P| 60秒免费视频| 91欧洲国产成人久久精品网站| 日韩在线性爱免费视频| 婷婷五月天_亚洲小说欧美激情另类_精品久久国产字幕 | 91+欧美| 九九热re99re6在线精品| 日产操逼| 欧亚免费视频| 欧美老妇女内射网址| 91爱剪切久久| 26UUU欧美激情一区二区| 99久久久| 性高潮久久久| 韩国手机不卡无码三级视频| 欧美啪啪女女| 久久久禁| 国产精品久久久| 囯戸精品高潮呻吟旡码| 激情五月综合网| 青草伊人久久| 91动漫操逼视频| 欧美日韩人人精品| 中文字幕乱亚洲美女精品一区| 久久九九视频九九视频| 国产农村妇女精品一二区| 91n处女在线观看| 操逼逼中文字幕| 97色涩| 午夜小电影在线插入淫高潮| 日韩三级一区| 国产农村妇女毛片精品久久| 色就色综合| 国产suv精品一区二区四| 91综合天天看| 97最新在线播放视频| 亚洲麻豆18发?| 人人妻人人爽 97人人看碰人免费公开视频| 国产99精品一区二区三区免费| 亚洲精品99| av2014 日韩在线中文字幕| 亚洲成A∨人影院在线欢看| 日日夜夜草草草| 色欲无码人妻日韩欧美精品| 婷婷伊人一区| 日韩免费av片高清无码| 久久不卡一区二区| 欧美色999| 综合五月天| 超碰色大香蕉| 男人天堂一区二区| com 首页 18岁 禁区 女优 免费 精选 同城| 蜜臀久久99精品久久久| 婷婷三区| 国产女人视频三四五区| 天天干天天干天天干| 色婷婷一区二区三区久久| 超碰狠狠操| 玖草在线视频| 久久久久密臀视频| 久久久久久国产手机AV| 国产吹潮女在线观看| 国产h片在线观看视频| 天堂在线一区二区| 天天做日日做天天欢。| 超碰 国产熟女精品一区| 翔田千里av一区二区三区| 五月天精品| 色香阁在线| 思思视频免费看网站| 国产青视频| 老熟妇一区二区三区…| 亚洲图片视频小说| 天堂岛av| 国产一区二区免费福利片| 福利风月五月天影院| 亚洲精品白浆高清久久久久久 | 伊人国产AV| 亚洲国产激情国产av| 青青草公开在线免费不卡视频| 欧美熟妇视频| 亚洲资源站| 国产成自自拍在线观看| 国产AV色黄看到爽| 精品综合久久久久久97| 蜜桃久久综合视频| 久久久久久人妻一区精品色欧美| 亚洲区限制级| 99久久99九九99九九九| 五月丁香黄色网| 日日夜夜模| 九月婷婷久久| 思思热在线视频免费| 国产人人干| 丝袜制服字幕在线| 最新三级网址| 欧美少妇人妻| 夜夜免费视频| 中文字幕五区| av网站在线看| 91精品久久久久久| 青青青操| 2024人人操人人摸| 熟女这里只有精品6| 青青草五月份天| 91爱做| 亚洲国产欧美中文永久| 黄片www视频免费| 夜色97| 天天射影院| 极品美女福利在线观看| 无遮挡男女激烈动态图| 色香91| 亚州色图欧美| 熟女日韩| 久久久精品国产亚洲AV无码| 日本一卡二区在线| 亚爽爽爽爽爽爽爽爽| 欧美激情五月天| wwwcaobibi| 91香蕉视频在线观看免费| 美女黄色91| 丝袜色综合| oumeizonghese,www| 嗯嗯嗯好爽| 手机在线人成免费视频| 日婷婷| 国产精品久久久久久久久久久久| 久久是精品| 精品国产一区二区三区久久久蜜臀| 日亚韩精品视频二区三| 可以在线观看的黄色网址| 中日韩一区二区三区欧美| 可乐操亚洲蜜911| 中文一区在线日| 欧美日韩一干二干| 女同亚洲欧美一二三区久久电影| 人人爱操| 久久久久久AⅤ无码免费肉站| 黄片免费视频2019| 欧美性爱精品七区| 亚洲精品久久久久毛片A片拉屎 | 爱妃国产亚洲视频中文字幕| 91人妻少妇| 嫩草黄页| 天欧美在线| 欧美在线综合| 天天干人妻| 91久久久老司机| 男女激情中文字幕| 嗯啊啊啊轻点视频 | 二级久久网| 97色涩| 乱码熟妇人妻久久久| 久久久国产精品人妻丝袜| 久操B网| 无码heyzo高清一区| 亚洲AV乱码专区国产噜噜亚洲| 99精品丰满人妻无| 五月天婷婷基地| 性吧在线视频| 狼人综合婷婷激情四射 | 狠狠色丁香| 情色AV电影| 亚洲不卡AV在线| 亚洲最大的黄色电影网站。| 91国产大片| 99RE在线视频精品,这里只有精品|