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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

项目学生:分片集成测试数据

發布時間:2023/12/3 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 项目学生:分片集成测试数据 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

這是Project Student的一部分。 其他職位包括帶有Jersey的 Web服務 客戶端,帶有Jersey的 Web服務服務器 , 業務層和帶有Spring Data的持久性 。

到目前為止,所有集成測試都使用了內存嵌入式數據庫,該數據庫無法一次又一次地保留信息。 當我們將REST服務器與“真實”數據庫服務器完全集成時,這種情況會發生變化-剩余的測試數據將污染我們的開發或測試數據庫。 一旦我們進行了運行集成測試代碼的連續集成,這將是一個非常頭疼的事情。

一種解決方案是以一種允許我們的測試使用共享開發數據庫而不污染它或其他測試的方式“分片”我們的集成測試數據。 最簡單的方法是將TestRun字段添加到所有對象。 “測試”數據將具有指示特定測試運行的值,“實時”數據將具有空值。

確切的時間表是

  • 創建并持久保存一個TestRun對象
  • 創建具有適當TestRun值的測試對象
  • 執行集成測試
  • 刪除測試對象
  • 刪除TestRun對象
  • TestRun表中的??任何條目將是1)主動集成測試或2)引發未處理異常的集成測試失敗(當然,這取決于事務管理器)。 重要的是要注意,即使事務管理器執行了回滾,我們也可以在引發意外異常后捕獲數據庫狀態-這是對junit測試運行程序的簡單擴展。

    時間戳記和用戶字段使您可以輕松地根據其年齡(例如,超過7天的任何測試)或運行測試的人員刪除陳舊的測試數據。

    TestablePersistentObject抽象基類

    此更改從持久性級別開始,因此我們應該從持久性級別開始并逐步進行擴展。

    我們首先用測試運行值擴展PersistentObject抽象基類。

    @MappedSuperclass public abstract class TestablePersistentObject extends PersistentObject {private static final long serialVersionUID = 1L;private TestRun testRun;/*** Fetch testRun object. We use lazy fetching since we rarely care about the* contents of this object - we just want to ensure referential integrity to* an existing testRun object when persisting a TPO.* * @return*/@ManyToOne(fetch = FetchType.LAZY, optional = true)public TestRun getTestRun() {return testRun;}public void setTestRun(TestRun testRun) {this.testRun = testRun;}@Transientpublic boolean isTestData() {return testRun != null;} }

    TestRun類

    TestRun類包含有關單個集成測試運行的標識信息。 它包含一個名稱(默認情況下,該集成測試為classname#methodname()) ,測試的日期和時間以及運行該測試的用戶的名稱。 捕獲其他信息將很容易。

    測試對象列表為我們帶來了兩個重大勝利。 首先,如果需要(例如,在意外的異常之后),可以輕松捕獲數據庫的狀態。 其次,級聯刪除使刪除所有測試對象變得容易。

    @XmlRootElement @Entity @Table(name = "test_run") @AttributeOverride(name = "id", column = @Column(name = "test_run_pkey")) public class TestRun extends PersistentObject {private static final long serialVersionUID = 1L;private String name;private Date testDate;private String user;private List<TestablePersistentObject> objects = Collections.emptyList();@Column(length = 80, unique = false, updatable = true)public String getName() {return name;}public void setName(String name) {this.name = name;}@Column(name = "test_date", nullable = false, updatable = false)@Temporal(TemporalType.TIMESTAMP)public Date getTestDate() {return testDate;}public void setTestDate(Date testDate) {this.testDate = testDate;}@Column(length = 40, unique = false, updatable = false)public String getUser() {return user;}public void setUser(String user) {this.user = user;}@OneToMany(cascade = CascadeType.ALL)public List<TestablePersistentObject> getObjects() {return objects;}public void setObjects(List<TestablePersistentObject> objects) {this.objects = objects;}/*** This is similar to standard prepersist method but we also set default* values for everything else.*/@PrePersistpublic void prepersist() {if (getCreationDate() == null) {setCreationDate(new Date());}if (getTestDate() == null) {setTestDate(new Date());}if (getUuid() == null) {setUuid(UUID.randomUUID().toString());}if (getUser() == null) {setUser(System.getProperty("user.name"));}if (name == null) {setName("test run " + getUuid());}} }

    TestRun類擴展了PersistentObject,而不是TestablePersistentObject,因為我們的其他集成測試將充分利用它。

    Spring數據倉庫

    我們必須向每個存儲庫添加一種其他方法。

    @Repository public interface CourseRepository extends JpaRepository {List<Course> findCoursesByTestRun(TestRun testRun);.... }

    服務介面

    同樣,我們必須為每個服務添加兩個其他方法。

    public interface CourseService {List<Course> findAllCourses();Course findCourseById(Integer id);Course findCourseByUuid(String uuid);Course createCourse(String name);Course updateCourse(Course course, String name);void deleteCourse(String uuid);// new method for testingCourse createCourseForTesting(String name, TestRun testRun);// new method for testingList<Course> findAllCoursesForTestRun(TestRun testRun); }

    我不會顯示TestRunRepository,TestRunService接口或TestRunService實現,因為它們與我在前幾篇博客文章中所描述的相同。

    服務實施

    我們必須對現有Service實施進行一次小的更改,并添加兩種新方法。

    @Service public class CourseServiceImpl implements CourseService {@Resourceprivate TestRunService testRunService;/*** @see com.invariantproperties.sandbox.student.business.CourseService#* findAllCourses()*/@Transactional(readOnly = true)@Overridepublic List<Course> findAllCourses() {List<Course> courses = null;try {courses = courseRepository.findCoursesByTestRun(null);} catch (DataAccessException e) {if (!(e instanceof UnitTestException)) {log.info("error loading list of courses: " + e.getMessage(), e);}throw new PersistenceException("unable to get list of courses.", e);}return courses;}/*** @see com.invariantproperties.sandbox.student.business.CourseService#* findAllCoursesForTestRun(com.invariantproperties.sandbox.student.common.TestRun)*/@Transactional(readOnly = true)@Overridepublic List<Course> findAllCoursesForTestRun(TestRun testRun) {List<Course> courses = null;try {courses = courseRepository.findCoursesByTestRun(testRun);} catch (DataAccessException e) {if (!(e instanceof UnitTestException)) {log.info("error loading list of courses: " + e.getMessage(), e);}throw new PersistenceException("unable to get list of courses.", e);}return courses;}/*** @see com.invariantproperties.sandbox.student.business.CourseService#* createCourseForTesting(java.lang.String,* com.invariantproperties.sandbox.student.common.TestRun)*/@Transactional@Overridepublic Course createCourseForTesting(String name, TestRun testRun) {final Course course = new Course();course.setName(name);course.setTestUuid(testRun.getTestUuid());Course actual = null;try {actual = courseRepository.saveAndFlush(course);} catch (DataAccessException e) {if (!(e instanceof UnitTestException)) {log.info("internal error retrieving course: " + name, e);}throw new PersistenceException("unable to create course", e);}return actual;} }

    CourseServiceIntegrationTest

    我們對集成測試進行了一些更改。 我們只需更改一種測試方法,因為它是唯一實際創建測試對象的方法。 其余方法是不需要測試數據的查詢。

    請注意,我們更改名稱值以確保其唯一性。 這是解決唯一性約束(例如,電子郵件地址)的一種方法。

    @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = { BusinessApplicationContext.class, TestBusinessApplicationContext.class,TestPersistenceJpaConfig.class }) @Transactional @TransactionConfiguration(defaultRollback = true) public class CourseServiceIntegrationTest {@Resourceprivate CourseService dao;@Resourceprivate TestRunService testService;@Testpublic void testCourseLifecycle() throws Exception {final TestRun testRun = testService.createTestRun();final String name = "Calculus 101 : " + testRun.getUuid();final Course expected = new Course();expected.setName(name);assertNull(expected.getId());// create courseCourse actual = dao.createCourseForTesting(name, testRun);expected.setId(actual.getId());expected.setUuid(actual.getUuid());expected.setCreationDate(actual.getCreationDate());assertThat(expected, equalTo(actual));assertNotNull(actual.getUuid());assertNotNull(actual.getCreationDate());// get course by idactual = dao.findCourseById(expected.getId());assertThat(expected, equalTo(actual));// get course by uuidactual = dao.findCourseByUuid(expected.getUuid());assertThat(expected, equalTo(actual));// get all coursesfinal List<Course> courses = dao.findCoursesByTestRun(testRun);assertTrue(courses.contains(actual));// update courseexpected.setName("Calculus 102 : " + testRun.getUuid());actual = dao.updateCourse(actual, expected.getName());assertThat(expected, equalTo(actual));// verify testRun.getObjectsfinal List<TestablePersistentObject> objects = testRun.getObjects();assertTrue(objects.contains(actual));// delete Coursedao.deleteCourse(expected.getUuid());try {dao.findCourseByUuid(expected.getUuid());fail("exception expected");} catch (ObjectNotFoundException e) {// expected}testService.deleteTestRun(testRun.getUuid());}.... }

    我們可以使用@Before和@After透明地包裝所有測試方法,但是許多測試不需要測試數據,而許多需要測試數據的測試則需要唯一的測試數據,例如,電子郵件地址。 在后一種情況下,我們按照上述方法折疊測試UUID。

    REST Web服務服務器

    REST Web服務需要在請求類中添加測試uuid,并在創建對象時添加一些邏輯以正確處理它。

    REST Web服務不支持獲取所有測試對象的列表。 “正確”的方法將是創建TestRun服務并響應/ get / {id}查詢提供關聯的對象。

    @XmlRootElement public class Name {private String name;private String testUuid;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getTestUuid() {return testUuid;}public void setTestUuid(String testUuid) {this.testUuid = testUuid;} }

    現在,我們可以檢查可選的testUuid字段并調用適當的create方法。

    @Service @Path("/course") public class CourseResource extends AbstractResource {@Resourceprivate CourseService service;@Resourceprivate TestRunService testRunService;/*** Create a Course.* * @param req* @return*/@POST@Consumes({ MediaType.APPLICATION_JSON, MediaType.TEXT_XML })@Produces({ MediaType.APPLICATION_JSON, MediaType.TEXT_XML })public Response createCourse(Name req) {log.debug("CourseResource: createCourse()");final String name = req.getName();if ((name == null) || name.isEmpty()) {return Response.status(Status.BAD_REQUEST).entity("'name' is required'").build();}Response response = null;try {Course course = null;if (req.getTestUuid() != null) {TestRun testRun = testRunService.findTestRunByUuid(req.getTestUuid());if (testRun != null) {course = service.createCourseForTesting(name, testRun);} else {response = Response.status(Status.BAD_REQUEST).entity("unknown test UUID").build();}} else {course = service.createCourse(name);}if (course == null) {response = Response.status(Status.INTERNAL_SERVER_ERROR).build();} else {response = Response.created(URI.create(course.getUuid())).entity(scrubCourse(course)).build();}} catch (Exception e) {if (!(e instanceof UnitTestException)) {log.info("unhandled exception", e);}response = Response.status(Status.INTERNAL_SERVER_ERROR).build();}return response;}.... }

    REST Web服務客戶端

    最后,REST服務器必須添加一種其他方法。 客戶端尚不支持獲取所有測試對象的列表。

    public interface CourseRestClient {/*** Create specific course for testing.* * @param name* @param testRun*/Course createCourseForTesting(String name, TestRun testRun);.... }

    public class CourseRestClientImpl extends AbstractRestClientImpl implements CourseRestClient {/*** Create JSON string.* * @param name* @return*/String createJson(final String name, final TestRun testRun) {return String.format("{ \"name\": \"%s\", \"testUuid\": \"%s\" }", name, testRun.getTestUuid());}/*** @see com.invariantproperties.sandbox.student.webservice.client.CourseRestClient#createCourse(java.lang.String)*/@Overridepublic Course createCourseForTesting(final String name, final TestRun testRun) {if (name == null || name.isEmpty()) {throw new IllegalArgumentException("'name' is required");}if (testRun == null || testRun.getTestUuid() == null || testRun.getTestUuid().isEmpty()) {throw new IllegalArgumentException("'testRun' is required");}return createObject(createJson(name, testRun));}.... }

    源代碼

    可從http://code.google.com/p/invariant-properties-blog/source/browse/student獲取源代碼。

    澄清度

    我認為在TestRun中不可能有@OneToMany到TestablePersistentObject,但是使用H2的集成測試成功了。 不幸的是,當我使用PostgreSQL數據庫啟動完全集成的Web服務時,這會引起問題。 我將代碼留在上面,因為即使我們沒有通用集合,也總是可以有一個教室列表,一個課程列表等。 但是,代碼已從源代碼控制的版本中刪除。

    更正

    接口方法應該是findCourseByTestRun_Uuid() ,而不是findCourseByTestRun() 。 另一種方法是使用JPA標準查詢–請參閱“ 項目學生:JPA標準查詢” 。

    參考: 項目學生:來自Invariant Properties博客的JCG合作伙伴 Bear Giles提供的分片集成測試數據 。

    翻譯自: https://www.javacodegeeks.com/2014/01/project-student-sharding-integration-test-data.html

    總結

    以上是生活随笔為你收集整理的项目学生:分片集成测试数据的全部內容,希望文章能夠幫你解決所遇到的問題。

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

    主站蜘蛛池模板: 久久精品1 | 国产精品亚洲一区二区三区在线观看 | 精品久久久网站 | 天堂网男人 | 亚洲激情在线播放 | 大黑人交交护士xxxxhd | 深夜天堂 | 精品免费视频一区二区 | 亚洲天堂日本 | 日本系列第一页 | 五十路六十路七十路熟婆 | 无码人妻aⅴ一区二区三区有奶水 | 色又黄又爽 | 极品少妇xxxx | 激情瑟瑟 | 欧美日韩不卡一区二区三区 | 九九视频这里只有精品 | 天堂www中文在线资源 | 久久久精品国产sm调教网站 | 越南黄色一级片 | 免费成人小视频 | 久久私人影院 | 男男play呻吟动漫网站 | 久久久精品一区 | 两口子交换真实刺激高潮 | 插综合 | 丰满少妇高潮在线观看 | 荡女精品导航 | 国产毛片一区 | 四虎午夜 | 色小姐综合 | 色交视频 | 人妻熟女一区二区aⅴ水 | 国产精品久久久久久久9999 | 精品国产中文字幕 | 精品国产精品 | 亚洲资源网站 | 亚洲色图视频在线 | 黑人添美女bbb添高潮了 | 久久性爱视频网站 | 91视频免费在观看 | 丰满人妻一区二区三区免费视频棣 | 国产久久精品 | 日韩在线视频免费观看 | 日本一区二区三区久久 | 午夜视频一区 | 综合久 | 香蕉综合网 | 婷婷影音 | 日本天堂网 | 都市激情亚洲色图 | 中文字幕无码人妻少妇免费 | 久久久一区二区三区四区 | 精品一区二区三区四区五区六区 | 中国少妇初尝黑人巨大 | 魔性诱惑 | 国产精品久久国产精麻豆96堂 | 久久久久麻豆 | 中文字幕1区2区 | 91干网| 国产一级啪啪 | 美女啪啪一区二区 | 日日操狠狠操 | 好吊操这里有精品 | 男女性杂交内射妇女bbwxz | 九九免费视频 | 日本午夜电影 | 久久99精品国产麻豆婷婷洗澡 | 女人又爽又黄免费女仆 | 一区免费在线 | 一区二区视频 | 亚洲精品日本 | 亚洲成人自拍偷拍 | 国模av | 天天操天天舔天天干 | 欧美伦理片网站 | a视频免费看 | 人妻少妇被猛烈进入中文字幕 | 在线免费日韩 | 欧洲精品二区 | 精品视频在线观看免费 | 国产a一级片 | 日本午夜视频 | 日日插插 | 国产成人自拍网 | 九九热视频精品在线观看 | www.嫩草.com| 欧美寡妇性猛交 | 中国女人做爰视频 | 精品人妻无码一区二区三区 | va在线播放 | 妞干网这里只有精品 | 波多野结衣影片 | 特级免费毛片 | 亚洲精品一区二区三区影院忠贞 | 波多野av在线 | 亚洲91网 | 激情四射网站 | 成人爱爱网站 |