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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

在Spring Boot项目中使用Spock框架

發布時間:2025/4/16 javascript 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 在Spring Boot项目中使用Spock框架 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載:https://www.jianshu.com/p/f1e354d382cd

Spock框架是基于Groovy語言的測試框架,Groovy與Java具備良好的互操作性,因此可以在Spring Boot項目中使用該框架寫優雅、高效以及DSL化的測試用例。Spock通過@RunWith注解與JUnit框架協同使用,另外,Spock也可以和Mockito(Spring Boot應用的測試——Mockito)協同使用。

在這個小節中我們會利用Spock、Mockito一起編寫一些測試用例(包括對Controller的測試和對Repository的測試),感受下Spock的使用。

How Do

  • 根據Building an Application with Spring Boot這篇文章的描述,spring-boot-maven-plugin這個插件同時也支持在Spring Boot框架中使用Groovy語言。
  • 在pom文件中添加Spock框架的依賴
<!-- test --> <dependency><groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.spockframework</groupId> <artifactId>spock-core</artifactId> <scope>test</scope></dependency> <dependency> <groupId>org.spockframework</groupId> <artifactId>spock-spring</artifactId> <scope>test</scope> </dependency>
  • 在src/test目錄下創建groovy文件夾,在groovy文件夾下創建com/test/bookpub包。
  • 在resources目錄下添加packt-books.sql文件,內容如下所示:
INSERT INTO author (id, first_name, last_name) VALUES (5, 'Shrikrishna', 'Holla'); INSERT INTO book (isbn, title, author, publisher) VALUES ('978-1-78398-478-7', 'Orchestrating Docker', 5, 1); INSERT INTO author (id, first_name, last_name) VALUES (6, 'du', 'qi'); INSERT INTO book (isbn, title, author, publisher) VALUES ('978-1-78528-415-1', 'Spring Boot Recipes', 6, 1);
  • 在com/test/bookpub目錄下創建SpockBookRepositorySpecification.groovy文件,內容是:
package com.test.bookpubimport com.test.bookpub.domain.Authorimport com.test.bookpub.domain.Book import com.test.bookpub.domain.Publisher import com.test.bookpub.repository.BookRepository import com.test.bookpub.repository.PublisherRepository import org.mockito.Mockito import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.SpringApplicationContextLoader import org.springframework.context.ConfigurableApplicationContext import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator import org.springframework.test.context.ContextConfiguration import org.springframework.test.context.web.WebAppConfiguration import org.springframework.test.web.servlet.MockMvc import org.springframework.test.web.servlet.setup.MockMvcBuilders import spock.lang.Sharedimport spock.lang.Specification import javax.sql.DataSourceimport javax.transaction.Transactional import static org.hamcrest.Matchers.containsString; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @WebAppConfiguration @ContextConfiguration(classes = [BookPubApplication.class, TestMockBeansConfig.class],loader = SpringApplicationContextLoader.class) class SpockBookRepositorySpecification extends Specification { @Autowired private ConfigurableApplicationContext context; @Shared boolean sharedSetupDone = false; @Autowired private DataSource ds; @Autowired private BookRepository bookRepository; @Autowired private PublisherRepository publisherRepository; @Shared private MockMvc mockMvc; void setup() { if (!sharedSetupDone) { mockMvc = MockMvcBuilders.webAppContextSetup(context).build(); sharedSetupDone = true; } ResourceDatabasePopulator populator = new ResourceDatabasePopulator(context.getResource("classpath:/packt-books.sql")); DatabasePopulatorUtils.execute(populator, ds); } @Transactional def "Test RESTful GET"() { when: def result = mockMvc.perform(get("/books/${isbn}")); then: result.andExpect(status().isOk()) result.andExpect(content().string(containsString(title))); where: isbn | title "978-1-78398-478-7"|"Orchestrating Docker" "978-1-78528-415-1"|"Spring Boot Recipes" } @Transactional def "Insert another book"() { setup: def existingBook = bookRepository.findBookByIsbn("978-1-78528-415-1") def newBook = new Book("978-1-12345-678-9", "Some Future Book", existingBook.getAuthor(), existingBook.getPublisher()) expect: bookRepository.count() == 3 when: def savedBook = bookRepository.save(newBook) then: bookRepository.count() == 4 savedBook.id > -1 } }
  • 執行測試用例,測試通過
  • 接下來試驗下Spock如何與mock對象一起工作,之前的文章中我們已經在TestMockBeansConfig類中定義了PublisherRepository的Spring Bean,如下所示,由于@Primary的存在,使得在運行測試用例時Spring Boot優先使用Mockito框架模擬出的實例。
@Configuration @UsedForTesting public class TestMockBeansConfig { @Bean @Primary public PublisherRepository createMockPublisherRepository() { return Mockito.mock(PublisherRepository.class); } }
  • 在BookController.java中添加getBooksByPublisher接口,代碼如下所示:
@Autowired public PublisherRepository publisherRepository;@RequestMapping(value = "/publisher/{id}", method = RequestMethod.GET) public List<Book> getBooksByPublisher(@PathVariable("id") Long id) { Publisher publisher = publisherRepository.findOne(id); Assert.notNull(publisher); return publisher.getBooks(); }
  • 在SpockBookRepositorySpecification.groovy文件中添加對應的測試用例,
def "Test RESTful GET books by publisher"() { setup: Publisher publisher = new Publisher("Strange Books") publisher.setId(999) Book book = new Book("978-1-98765-432-1", "Mytery Book", new Author("Jhon", "Done"), publisher) publisher.setBooks([book]) Mockito.when(publisherRepository.count()). thenReturn(1L); Mockito.when(publisherRepository.findOne(1L)). thenReturn(publisher) when: def result = mockMvc.perform(get("/books/publisher/1")) then: result.andExpect(status().isOk()) result.andExpect(content().string(containsString("Strange Books"))) cleanup: Mockito.reset(publisherRepository) }
  • 運行測試用例,發現可以測試通過,在控制器將對象轉換成JSON字符串裝入HTTP響應體時,依賴Jackson庫執行轉換,可能會有循環依賴的問題——在模型關系中,一本書依賴一個出版社,一個出版社有包含多本書,在執行轉換時,如果不進行特殊處理,就會循環解析。我們這里通過@JsonBackReference注解阻止循環依賴。

分析

可以看出,通過Spock框架可以寫出優雅而強大的測試代碼。

首先看SpockBookRepositorySpecification.groovy文件,該類繼承自Specification類,告訴JUnit這個類是測試類。查看Specification類的源碼,可以發現它被@RunWith(Sputnik.class)注解修飾,這個注解是連接Spock與JUnit的橋梁。除了引導JUnit,Specification類還提供了很多測試方法和mocking支持。

Note:關于Spock的文檔見這里:Spock Framework Reference Documentation

根據《單元測試的藝術》一書中提到的,單元測試包括:準備測試數據、執行待測試方法、判斷執行結果三個步驟。Spock通過setup、expect、when和then等標簽將這些步驟放在一個測試用例中。

  • setup:這個塊用于定義變量、準備測試數據、構建mock對象等;
  • expect:一般跟在setup塊后使用,包含一些assert語句,檢查在setup塊中準備好的測試環境
  • when:在這個塊中調用要測試的方法;
  • then : 一般跟在when后使用,盡可以包含斷言語句、異常檢查語句等等,用于檢查要測試的方法執行后結果是否符合預期;
  • cleanup:用于清除setup塊中對環境做的修改,即將當前測試用例中的修改回滾,在這個例子中我們對publisherRepository對象執行重置操作。

Spock也提供了setup()和cleanup()方法,執行一些給所有測試用例使用的準備和清除動作,例如在這個例子中我們使用setup方法:(1)mock出web運行環境,可以接受http請求;(2)加載packt-books.sql文件,導入預定義的測試數據。web環境只需要Mock一次,因此使用sharedSetupDone這個標志來控制。

通過@Transactional注解可以實現事務操作,如果某個方法被該注解修飾,則與之相關的setup()方法、cleanup()方法都被定義在一個事務內執行操作:要么全部成功、要么回滾到初始狀態。我們依靠這個方法保證數據庫的整潔,也避免了每次輸入相同的數據。



作者:杜琪
鏈接:https://www.jianshu.com/p/f1e354d382cd
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。

轉載于:https://www.cnblogs.com/ceshi2016/p/8442470.html

總結

以上是生活随笔為你收集整理的在Spring Boot项目中使用Spock框架的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 性一交一乱一色一视频麻豆 | 黄色视屏在线免费观看 | 美女黄色av| 中文字幕电影一区 | 亚洲加勒比 | 五月婷婷激情综合网 | 老湿机69福利区午夜x片 | 免费黄色一级 | 大屁股白浆一区二区 | 欧美色交 | 国产偷v| 毛片久久久久久久 | 好男人www在线视频 我们的2018在线观看免费高清 | 夜夜爽妓女8888视频免费观看 | 成人黄色录像 | 日韩高清影院 | 女优视频在线观看 | www四虎精品视频免费网站 | 色女人av| 日本少妇bb | 国产吃瓜黑料一区二区 | 黄色片视频免费在线观看 | 日韩精品久久 | 日本午夜电影 | 国产精品麻豆视频 | 国产片网址 | 特黄一级大片 | 午夜视频91 | 九九热九九热 | 福利国产片 | 91久久久久一区二区 | eeuss一区二区三区 | 脱裤吧导航 | 美女让男人捅 | 日韩综合久久 | 亚洲一区二区三区在线视频观看 | 国产一区二区视频在线 | 国产又爽又黄免费软件 | 黄色网址大全免费 | 好吊操妞| 国产精久久一区二区三区 | 老子影院午夜精品无码 | 伊人9999| 久久亚洲AV成人无码国产人妖 | 免费av毛片| 欧美久久久久 | 色偷偷噜噜噜亚洲男人的天堂 | 国产看片网站 | 国产第十页 | 亚洲国产一区在线观看 | 久草国产精品 | 欧美9999 | 亚洲无套 | 国产成人无码精品久久久久 | 婷婷综合视频 | 国内精品国产成人国产三级 | 欧美aaa一级片| 中文字幕 视频一区 | 毛片视频免费 | 欧美精品播放 | 精品人妻人人做人人爽 | 欧美性久久久久 | 成人亚洲网站 | 九九热这里都是精品 | 本道久久 | 中文字幕一区二区三区在线观看 | 免费观看在线高清 | 亚洲国产日韩一区无码精品久久久 | 欧美午夜三级 | 91婷婷在线| 国产啊v在线观看 | 悟空影视大全免费高清观看在线 | 精品九九视频 | 无码人妻精品中文字幕 | 国产精品s色 | 国产成人免费av一区二区午夜 | 色爱av综合网 | 欧美日韩久久久久久 | 另类二区| 国产又黄又猛又爽 | 久久久视频在线 | 中国一级特黄录像播放 | 夜夜高潮夜夜爽 | 亚洲自啪 | 国产人成无码视频在线观看 | 精品免费国产一区二区三区四区 | 日本特黄一级 | 日批免费看 | 久久免费精彩视频 | 亚洲国产精品成人综合久久久 | 久久久久亚洲AV成人网人人小说 | 深夜免费福利 | 亚洲国产精品免费视频 | 91视频一区二区三区 | 成人a毛片| 国产免费激情 | 黄页网站视频 | 欧美另类高清 | 久久精品一级片 |