英文:
How to test entities which have not null foreign key constraints
问题
我有十几个类似Product
, Category
, Customer
, Order
等的表格...
它们之间有not null
的关联关系。我创建了ORM
,现在正在进行测试。
然而,我觉得这相当繁琐,因为为了测试例如必须属于Customer
的Order
实体(即执行persist
操作),我还必须创建Customer
实例。更进一步:因为Order
不能单独存在于Product
之外,所以我必须创建Product
并将其添加到Order
中。Product
必须属于某个Category
,依此类推。因此,您可以看到一系列强制性关系,这使得测试单个实体变得非常困难。
自然的解决方案是将约束检查推迟到提交时(Oracle):
alter session set constraints=deferred;
然而,我发现了一些信息,即Hibernate
不关心推迟约束(支持延迟约束)。
这是否意味着持久性测试必须如此麻烦,还是我可以做得更好/不同?
我认为数据库约束是神圣的,所以因为Hibernate不支持而放弃它们听起来不太好。
英文:
I have a dozen of tables like Product
, Category
, Customer
, Order
, ...
with not null
relationships to one another. I created ORM
and right now I am in the middle of tests.
However I find it pretty tedious, because in order to test for example Order
entity which has to belong to Customer
(namely perform persist
operation) I have to create Customer
instance as well. Lets go further: because Order
cannot exist separately to Product
I have to create Product
and add it to Order
. Product
has to be in some Category
, and so on. So you can see a chain of mandatory relationships, which makes testing individual entity very difficult.
Natural solution would be to defer constraint check to commit (Oracle):
alter session set constraints=deferred;
However I found a piece of information that Hibernate
doesn't care of deferring (support for deferred constraint).
Does it mean, that persistence testing has to be so problematic or I can do it better/different?
I believe that db constraints are sacred, so resigning from them, because hibernate does not support it sounds bad.
答案1
得分: 2
你可以为测试目的创建工厂。它们的任务是创建一个有效的对象图。这样的类可以在任何类型的测试中使用(不仅限于存储库):
ProductFactory.withType(...).withOtherImportantOption(...).create()
如果你愿意,这样的工厂可以利用随机化,但这并不是强制性的。尽管对于具有唯一约束的字段,必须引入一定程度的随机化。
PS:不满足FK似乎是错误的路径 - 最终你将需要测试持久化许多对象,甚至可能提交事务。而且你可能还想测试级联操作。
英文:
You can create factories for test purposes. Their job is to create a graph of objects that are valid. Such class can be used in any kind of testing (not only the repositories):
ProductFactory.withType(...).withOtherImportantOption(...).create()
Such factory could leverage randomization if you wish, but it's not mandatory. Though some amount of randomization will have to be introduced for fields with unique constraints.
PS: not satisfying FK seems like a wrong path - you'll eventually need tests that persist many objects, maybe even commit transactions. And you may also want to test cascades.
答案2
得分: 1
为什么不创建一个预先填充了大量测试数据的测试数据库。
您可以在名为import.sql
的文件中定义测试数据,或者通过javax.persistence.sql-load-script-source
指定,它将由模式导出工具自动加载。
更新:明确一下,您只需要在每个表中添加几行测试数据,以便在测试对象时建立有效的引用。
例如,如果您想测试持久化一个Book
,您可以这样写:
Book b = new Book();
b.setTitle("Feersum Endjin");
b.setAuthor(em.getReference(Author.class, AUTHOR_ID));
em.persist(b);
其中AUTHOR_ID
是测试数据行的ID。
我认为这比编写使用不一致状态的对象(即具有空属性)和违反数据库约束的测试数据的测试要好得多。
英文:
Why not just create your test database prepopulated with a bunch of test data.
You can define test data in a file named import.sql
, or specified via javax.persistence.sql-load-script-source
, and it will be automatically loaded by the schema export tool.
UPDATE: To be clear, you only need a couple of rows of test data in each table, that you'll use in order to set up valid references from the objects you're testing.
For example, if you want to test persisting a Book
, you would write:
Book b = new Book();
b.setTitle("Feersum Endjin");
b.setAuthor( em.getReference(Author.class, AUTHOR_ID) );
em.persist(b);
Where AUTHOR_ID
is the id of a row of test data.
This is a lot better, IMO, than writing tests that work with objects in an inconsistent state (i.e. with null attributes) and test data that violates the database constraints.
答案3
得分: 0
如果您正在使用JPA,那么您的存储库将自动进行测试。如果您真的需要,那么请在此处查看。
希望这回答了您的问题。
英文:
If you're using JPA, then your repositories are tested automatically. If you really need to, then have a look here.
Hope this answers your question.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论