在單元測試之前,是否有一種最佳實踐模式,用於將數據庫完全重置爲使用JPA的新鋪好的模式?我一直在用hbml2ddl.auto = create-or-drop使用一個測試持久化單元,並在每次測試之前重新創建EMF,但我想知道是否有更簡單的方法來完成它。如何在每次測試之前重置JPA控制的數據庫?
回答
單元測試不應該跟數據庫。
假設你正在爲你的數據訪問層編寫一個集成測試,你可以使用一個工具,如DBUnit,或者你可以創建一個靜態測試助手,通過使用JPA執行所有的刪除和插入,以編程方式重置數據庫狀態查詢內部的事務。
你能證明你的初始斷言嗎? – HenryR 2010-09-10 05:44:42
我想說的理由是'因爲數據庫很慢'。當使用Oracle等等,甚至打開一個連接很慢時,這是真的。內存數據庫不是這樣。 – 2010-09-10 06:00:22
我想說的理由是「單元」測試應該單獨測試「單元」。一旦涉及數據庫,您就不會進行單元測試,而是進行集成測試。它與使用的數據庫類型無關。 – 2010-09-10 06:49:54
重置數據庫,如果你使用一個快速的Java數據庫,如H2 database或HSQLDB是不是一個大問題。與使用Oracle/MySQL(或任何用於生產的任何產品)相比,這將加快您的測試速度,並確保所有代碼都在使用「真實」生產數據庫時進行測試。
爲了獲得最大的性能,可以在內存中使用H2(這樣你可以不必手動重置數據庫 - 如果連接被關閉,它會自動重置),也可以使用普通持久的數據庫。要在H2中使用後重置數據庫,請運行(native)語句「刪除所有對象刪除文件」。
你如何強制連接關閉? – 2014-10-02 20:36:36
是否有一個最佳實踐模式,用於在單元測試之前使用JPA將數據庫完全重置爲新鋪好的模式?
不要在每個單元測試之前重置整個數據庫模式,而是在每個單元測試的結束時重置「數據庫環境(特定於當前單元測試)」。
我們有一個實體...
@Entity
public class Candidate implements {
private String id;
private String userName;
private EntityLifeCycle lifeCycle;
protected Candidate() {
}
public Candidate(String userName) {
this.userName = userName;
}
@Id @GeneratedValue(generator="uuid", strategy=GenerationType.AUTO)
@GenericGenerator(name="uuid", strategy="uuid", parameters = {})
@Column(name="candidate_id", nullable=false, unique=true)
public String getId() {
return id;
}
protected void setId(String id) {
this.id = id;
}
@Column(name="user_name", nullable=false, unique=true)
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
@Embedded
public EntityLifeCycle getLifeCycle() {
if(lifeCycle == null) {
lifeCycle = new EntityLifeCycleImpl();
}
return lifeCycle;
}
public void setLifeCycle(EntityLifeCycleImpl lifeCycle) {
this.lifeCycle = lifeCycle;
}
@PrePersist
public void prePersist() {
lifeCycle.setCreatedDate(new Date());
}
}
我們正在爲在prePersist(每個候選實例)方法createdDate。這裏是斷言createdDate是越來越正確設置一個測試用例....
public class EntityLifeCycleTest {
@Test
public void testLifeCycle() {
EntityManager manager = entityManagerFactory.createEntityManager();
Candidate bond = new Candidate("Miss. Bond");
EntityTransaction tx = manager.getTransaction();
tx.begin();
manager.persist(bond);
tx.commit();
Assert.assertNotNull(bond.getLifeCycle().getCreatedDate());
manager.close();
}
}
這個測試用例將首次運行正常。但是如果我們第二次運行這個測試用例,它會拋出ConstraintViolationException,因爲userName是唯一鍵。
因此,我認爲正確的做法是在每個測試用例的末尾「清理數據庫環境(特定於當前單元測試)」。像這樣...
public class EntityLifeCycleTest extends JavaPersistenceTest {
@Test
public void testLifeCycle() {
EntityManager manager = entityManagerFactory.createEntityManager();
Candidate bond = new Candidate("Miss. Bond");
EntityTransaction tx = manager.getTransaction();
tx.begin();
manager.persist(bond);
tx.commit();
Assert.assertNotNull(bond.getLifeCycle().getCreatedDate());
/* delete Candidate bond, so next time we can run this test case successfully*/
tx = manager.getTransaction();
tx.begin();
manager.remove(bond);
tx.commit();
manager.close();
}
}
我一直在使用一個測試持久單元與hbml2ddl.auto =創建-或降每次測試前和重建電磁場,但我不知道是否有一個更清潔的方式來做到這一點。
在每次測試之前重新創建EMF耗時,IMO。
只有在對影響底層數據庫的@Entity註釋類進行了一些更改(例如添加/刪除列和/或約束)時,才刪除並重新創建數據庫模式。因此,首先驗證架構,如果架構有效,則不要重新創建它,如果無效,則重新創建它。喜歡這個...現在
public class JavaPersistenceTest {
protected static EntityManagerFactory entityManagerFactory;
@BeforeClass
public static void setUp() throws Exception {
if(entityManagerFactory == null) {
Map<String, String> properties = new HashMap<String, String>(1);
try {
properties.put("hibernate.hbm2ddl.auto", "validate");
entityManagerFactory = Persistence.createEntityManagerFactory("default", properties);
} catch (PersistenceException e) {
e.printStackTrace();
properties.put("hibernate.hbm2ddl.auto", "create");
entityManagerFactory = Persistence.createEntityManagerFactory("default", properties);
}
}
}
}
,如果你運行所有的測試用例一氣呵成(擴展JavaPersistenceTest)時,EMF將創建只有一次(或兩次,如果模式無效)。
我不同意,[良好的設置不需要清理!](http://www.dbunit.org/bestpractices.html#nocleanup) – 2010-09-10 06:47:15
@PascalThivent它並不總是如此。如果有例如一個findAll()方法的測試,我想確保數據庫中沒有比我預期更多的記錄,那麼是的,我希望在測試之前清理所有其他記錄。即使這個數據庫是我的,我想保持清楚,因爲它是必要的。 – 2012-03-17 17:38:16
DBUnit的有很大你需要什麼,我用溫泉測試框架的回滾,在每次試驗後交易看http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/testing.html
- 1. 如何在每次測試之前讓Rails測試數據庫重建?
- 2. 如何在每次測試之前重置仿真器數據庫?
- 3. 在運行JUnit測試之前重置mysql數據庫
- 4. 如何在使用jeeunit進行每次測試後重置數據庫?
- 5. 如何在Android測試的每次測試之前設置Eclipse以運行登錄Junit測試?
- 6. 如何在每次「lein測試」之前運行Clojure代碼?
- 7. 每次測試前加載SQL數據庫
- 8. JUnit @Before和@After在每次測試之前和之後執行
- 9. Symfony 1.4 Doctrine重置數據前測試
- 10. 如何在每次發貨前強制重置?
- 11. 在每個套件之前運行摩卡設置而不是在每次測試之前
- 12. Codeception CEST acceptanse測試,如何在每次測試之前重新運行__bootstrap代碼?
- 13. VS2010負載測試:如何執行在每次負載測試之前運行一次的自定義操作
- 14. 如何在測試之前從開發數據庫加載數據?
- 15. Rails Rspec測試重置數據庫
- 16. 在每次測試之前重新設定FactoryGirl中序列的正確方法
- 17. azk - 如何設置測試數據庫?
- 18. 在每次測試之前在摩卡套件中設置變量?
- 19. 在每次測試之前都無法獲得所需文件
- 20. Spring AbstractTransactionalDataSourceSpringContextTests - 在每次Junit測試後防止數據庫回滾
- 21. 如何在每次運行htmlUnit或Selenium測試之前始終設置正確數量的標籤? Eclipse
- 22. 與遺留數據庫測試django應用程序 - 如何避免每個測試重新創建數據庫?
- 23. 將測試數據庫重建爲生產測試數據庫
- 24. 如何在每次測試之前使用kotlin-test框架初始化變量
- 25. 如何在每次「發佈」構建之前使用gradle執行Android測試?
- 26. 如何在處理任何數據之前測試open-uri url
- 27. 重複設置Moq控制器測試
- 28. 如何回滾,重置或刪除Ecto測試數據庫?
- 29. 如何重新部署,在每次測試運行時重新創建數據庫
- 30. FactoryGirl - 如何在運行測試之前在數據庫中生成類別條目的層次結構?
什麼是測試持久化單元?什麼是EMF?每次測試前你如何重現? – 2014-10-03 18:40:39