在Jersey 2中进行集成测试自定义验证约束
我最近加入了一個團隊,試圖將一個單一的遺留系統轉換為Java中的RESTful服務集。 他們決定使用最新的2.x版本的Jersey作為REST容器,這對我來說不是首選,因為我不是JSR- *規范的忠實擁護者。 但是現在我必須承認,JAX-RS 2.x的運行正確:需要幾乎零的樣板代碼,支持功能的自動發現,并且像其他現代框架一樣,更喜歡使用約定而不是配置。 由于該規范還很年輕,因此很難找到具有一些可用代碼的優秀教程和啟動項目。 我在GitHub上創建了jersey2-starter項目,該項目可用作您自己的生產就緒RESTful服務的起點。 在本文中,我想介紹如何實現和集成測試您自己的REST資源驗證約束。
自定義約束
用Java編寫REST時困擾我的問題之一是用注釋亂扔您的類模型。 假設您想構建一個簡單的Todo列表REST服務,當使用Jackson,validation和Spring Data時,您可以輕松地將其作為實體類結束:
@Document public class Todo {private Long id;@NotNullprivate String description;@NotNullprivate Boolean completed;@NotNullprivate DateTime dueDate;@JsonCreatorpublic Todo(@JsonProperty("description") String description, @JsonProperty("dueDate") DateTime dueDate) {this.description = description;this.dueDate = dueDate;this.completed = false;}// getters and setters }您的域模型現在幾乎到處都被混亂的注釋有效地模糊了。 讓我們看看如何使用驗證約束( @NotNull )。 有人可能會說您可以引入一些具有自己的驗證規則的DTO層,但是這與純REST API設計對我來說是沖突的,后者表示您在應映射到您的域類的資源上進行操作。 另一方面– Todo對象有效是什么意思? 創建Todo ,應提供說明和截止日期,但是更新時會怎樣? 您應該能夠更改描述,截止日期(推遲)和完成標志(標記為完成)中的任何一個,但是您至少應提供其中之一作為有效的修改。 所以我的想法是引入自定義驗證約束,用于創建和修改的約束不同:
@Target({TYPE, PARAMETER}) @Retention(RUNTIME) @Constraint(validatedBy = ValidForCreation.Validator.class) public @interface ValidForCreation {//...class Validator implements ConstraintValidator<ValidForCreation, Todo> {/...@Overridepublic boolean isValid(Todo todo, ConstraintValidatorContext constraintValidatorContext) {return todo != null&& todo.getId() == null&& todo.getDescription() != null&& todo.getDueDate() != null;}} }@Target({TYPE, PARAMETER}) @Retention(RUNTIME) @Constraint(validatedBy = ValidForModification.Validator.class) public @interface ValidForModification {//...class Validator implements ConstraintValidator<ValidForModification, Todo> {/...@Overridepublic boolean isValid(Todo todo, ConstraintValidatorContext constraintValidatorContext) {return todo != null&& todo.getId() == null&& (todo.getDescription() != null || todo.getDueDate() != null || todo.isCompleted() != null);}} }現在,您可以將驗證注釋移至REST端點的定義:
@POST @Consumes(APPLICATION_JSON) public Response create(@ValidForCreation Todo todo) {...}@PUT @Consumes(APPLICATION_JSON) public Response update(@ValidForModification Todo todo) {...}現在,您可以從模型中刪除那些NotNull 。
整合測試
集成測試通常有兩種方法:
- 測試是在與應用程序不同的JVM上運行的,而該應用程序已部署在其他集成環境中
- 測試在設置塊中以編程方式部署應用程序。
兩者都有其優點和缺點,但是對于足夠小的服務,我個人更喜歡第二種方法。 設置起來非常容易,并且您只啟動了一個JVM,這使得調試非常容易。 您可以使用Arquillian之類的通用框架在容器環境中啟動應用程序,但是我更喜歡簡單的解決方案,而只是使用嵌入式Jetty。 為了使測試設置100%等效于生產,我正在創建完整的Jetty的WebAppContext并且必須解決所有運行時相關性,才能使Jersey自動發現正常工作。 這可以通過Arrinklian子項目Shrinkwrap解決的Maven 輕松實現:
WebAppContext webAppContext = new WebAppContext();webAppContext.setResourceBase("src/main/webapp");webAppContext.setContextPath("/");File[] mavenLibs = Maven.resolver().loadPomFromFile("pom.xml").importCompileAndRuntimeDependencies().resolve().withTransitivity().asFile();for (File file: mavenLibs) {webAppContext.getMetaData().addWebInfJar(new FileResource(file.toURI()));}webAppContext.getMetaData().addContainerResource(new FileResource(new File("./target/classes").toURI()));webAppContext.setConfigurations(new Configuration[] {new AnnotationConfiguration(),new WebXmlConfiguration(),new WebInfConfiguration()});server.setHandler(webAppContext);( 此Stackoverflow線程在這里啟發了我很多)
現在是該文章最后一部分的時候了:參數化我們的集成測試。 由于我們要測試驗證約束,因此有許多要檢查的邊緣路徑(并使您的代碼覆蓋率接近100%)。 每個案例編寫一個測試可能是一個壞主意。 在實用的JUnit解決方案中,我最相信實用主義者團隊的Junit Params 。 它非常簡單,并且具有用于創建提供程序的類似于JQuery的幫助程序的概念。 這是我的測試代碼(我也在這里使用構建器模式來創建各種Todos):
@Test @Parameters(method = "provideInvalidTodosForCreation") public void shouldRejectInvalidTodoWhenCreate(Todo todo) {Response response = createTarget().request().post(Entity.json(todo));assertThat(response.getStatus()).isEqualTo(BAD_REQUEST.getStatusCode()); }private static Object[] provideInvalidTodosForCreation() {return $(new TodoBuilder().withDescription("test").build(),new TodoBuilder().withDueDate(DateTime.now()).build(),new TodoBuilder().withId(123L).build(),new TodoBuilder().build()); } OK,足夠的閱讀了,隨時克隆項目并開始編寫REST服務!
翻譯自: https://www.javacodegeeks.com/2014/03/integration-testing-custom-validation-constraints-in-jersey-2.html
總結
以上是生活随笔為你收集整理的在Jersey 2中进行集成测试自定义验证约束的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux文件夹的大小排序(linux文
- 下一篇: 二类医疗器械备案有效期多久(二类医疗器械