中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

spring boot之集成測試的示例分析

發布時間:2021-09-03 15:06:00 來源:億速云 閱讀:122 作者:小新 欄目:編程語言

這篇文章將為大家詳細講解有關spring boot之集成測試的示例分析,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

如果希望很方便針對API進行測試,并且方便的集成到CI中驗證每次的提交,那么spring boot自帶的IT絕對是不二選擇。

迅速編寫一個測試Case

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles({Profiles.ENV_IT})
public class DemoIntegrationTest{
  @Autowired
  private FooService fooService;
  @Test
  public void test(){
    System.out.println("tested");
  }
}

其中 SpringBootTest 定義了跑IT時的一些配置,上述代碼是用了隨機端口,當然也可以預定義端口,像這樣

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT, properties = {"server.port=9990"})

ActiveProfiles 強制使用了IT的Profile,從最佳實踐上來說IT Profile所配置的數據庫或者其他資源組件的地址,應該是與開發或者Staging環境隔離的。因為當一個IT跑完之后很多情況下我們需要清除測試數據。

你能夠發現這樣的Case可以使用 Autowired 注入任何想要的Service。這是因為spring將整個上下文都加載了起來,與實際運行的環境是一樣的,包含了數據庫,緩存等等組件。如果覺得測試時不需要全部的資源,那么在profile刪除對應的配置就可以了。這就是一個完整的運行環境,唯一的區別是當用例跑完會自動shutdown。

測試一個Rest API

強烈推薦一個庫,加入到gradle中

testCompile 'io.rest-assured:rest-assured:3.0.3'

支持JsonPath,十分好用,具體文檔戳 這里

@Sql(scripts = "/testdata/users.sql")
@Test
public void test001Login() {
  String username = "demo@demo.com";
  String password = "demo";
  JwtAuthenticationRequest request = new JwtAuthenticationRequest(username, password);
  Response response = given().contentType(ContentType.JSON).body(request)
      .when().post("/auth/login").then()
      .statusCode(HttpStatus.OK.value())
      .extract()
      .response();
  assertThat(response.path("token"), is(IsNull.notNullValue()));
  assertThat(response.path("expiration"), is(IsNull.notNullValue()));
}

@Sql 用于在測試前執行sql插入測試數據。注意 given().body() 中傳入的是一個java對象 JwtAuthenticationRequest ,因為rest-assured會自動幫你用 jackson 將對象序列化成json字符串。當然也可以將轉換好的json放到body,效果是一樣的。

返回結果被一個Response接住,之后就可以用JsonPath獲取其中數據進行驗證。當然還有一種更直觀的辦法,可以通過 response.asString() 獲取完整的response,再反序列化成java對象進行驗證。

至此,最基本的IT就完成了。 在Jenkins增加一個step gradle test 就可以實現每次提交代碼都進行一次測試。

一些復雜的情況

數據混雜

這是最容易發生,一個項目有很多dev,每個dev都會寫自己的IT case,那么如果數據之間產生了影響怎么辦。很容易理解,比如一個測試批量寫的場景,最后驗證方式是看寫的數據量是不是10w行。那么另外一個dev寫了其他的case恰好也新增了一條數據到這張表,結果變成了10w+1行,那么批量寫的case就跑不過了。

為了杜絕這種情況,我們采用每次跑完一個測試Class就將數據清空。既然是基于類的操作,可以寫一個基類解決。

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles({Profiles.ENV_IT})
public abstract class BaseIntegrationTest {
  private static JdbcTemplate jdbcTemplate;
  @Autowired
  public void setDataSource(DataSource dataSource) {
    jdbcTemplate = new JdbcTemplate(dataSource);
  }
  @Value("${local.server.port}")
  protected int port;
  @Before
  public void setupEnv() {
    RestAssured.port = port;
    RestAssured.basePath = "/api";
    RestAssured.baseURI = "http://localhost";
    RestAssured.config = RestAssured.config().httpClient(HttpClientConfig.httpClientConfig().httpMultipartMode(HttpMultipartMode.BROWSER_COMPATIBLE));
  }
  public void tearDownEnv() {
    given().contentType(ContentType.JSON)
        .when().post("/auth/logout");
  }
  @AfterClass
  public static void cleanDB() throws SQLException {
    Resource resource = new ClassPathResource("/testdata/CleanDB.sql");
    Connection connection = jdbcTemplate.getDataSource().getConnection();
    ScriptUtils.executeSqlScript(connection, resource);
    connection.close();
  }
}

@AfterClass 中使用了jdbcTemplate執行了一個CleanDB.sql,通過這種方式清除所有測試數據。

@Value("${local.server.port}") 也要提一下,因為端口是隨機的,那么Rest-Assured不知道請求要發到losthost的哪個端口上,這里使用 @Value 獲取當前的端口號并設置到 RestAssured.port 就解決了這個問題。

共有數據怎么處理

跑一次完整的IT,可能需要經歷數十個Class,數百個method,那么如果一些數據是所有case都需要的,只有在所有case都跑完才需要清除怎么辦?換句話說,這種數據清理不是基于 類 的,而是基于一次 運行 。比如初始用戶數據,城市庫等等

我們耍了個小聰明,借助了 flyway

@Configuration
@ConditionalOnClass({DataSource.class})
public class UpgradeAutoConfiguration {
  public static final String FLYWAY = "flyway";
  @Bean(name = FLYWAY)
  @Profile({ENV_IT})
  public UpgradeService cleanAndUpgradeService(DataSource dataSource) {
    UpgradeService upgradeService = new FlywayUpgradeService(dataSource);
    try {
      upgradeService.cleanAndUpgrade();
    } catch (Exception ex) {
      LOGGER.error("Flyway failed!", ex);
    }
    return upgradeService;
  }
}

可以看到當Profile是IT的情況下, flyway 會drop掉所有表并重新依次執行每次的upgrade腳本,由此創建完整的數據表,當然都是空的。在項目的test路徑下,增加一個版本極大的sql,這樣就可以讓 flyway 在最后插入共用的測試數據,例如 src/test/resources/db/migration/V999.0.1__Insert_Users.sql ,完美的解決各種數據問題。

關于“spring boot之集成測試的示例分析”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

呈贡县| 宿松县| 临清市| 哈巴河县| 海淀区| 拜城县| 互助| 绥宁县| 黄陵县| 郑州市| 香格里拉县| 兴仁县| 金坛市| 江油市| 玉溪市| 尖扎县| 湖南省| 佛坪县| 景谷| 大同县| 灌云县| 郯城县| 河南省| 赤峰市| 潮州市| 南平市| 衡水市| 灵武市| 隆昌县| 会昌县| 玉门市| 贺州市| 胶南市| 东城区| 莱州市| 共和县| 临朐县| 阿巴嘎旗| 南部县| 锡林浩特市| 连山|