Search code examples
testingpersistencefluent-interfacetest-data

Persisting complex test data


We are using builder pattern to generate test data. These domain objects have relations between them. Our functional tests require these objects to be persisted.

Think about this model:

domain model

If I want a plain instance of C I do aNew().c().build()

If I want it to be persisted I do aNew().c().saveIn(session)

If I want an instance of C with a known B I do aNew().c().with(b).build()

Well, you got the idea. My problem is, if I want to persist a C, should it persist it's B? Or should it be persisted before hand? What about if I want a reasonable default B? What about if I want to persist a D? Should it persist all A, B, C?

Of course real system is much more complex (sometimes with circular references). I am looking for a best practice for persisting complex test data.

Edit: It looks like I have bumped into the language barrier, my mother language is not English, so I am sorry for obscurity. Here is more information:

  • It is not legacy code that I am trying to test
  • I am trying to write a coverage test, NOT a unit test (as a result I won't be mocking anything)
  • The piece of software I am trying to test works if the database is populated to some extend (it does not use all entities).

PS. Please don't hesitate to ask for more information, because I have been struggling to find the possible best practice. The closest thing I have come up with is:

  1. Keep track of what has been set explicitly while building an entity.
  2. Assume that explicitly set entities are already persisted, do not persist them.
  3. Persist everything else (with their own persister).

This will work, but my spider sense is tingling, I think I am doing something wrong because, there will be logic involved in test code, it will be very complex to deal with without tests.

Edit 2: I will try to make myself more clear. When I am writing/running my unit and some integration tests I have no problem, because the test data are not persisted, it lives in memory.

But when I try to persist my test data, hibernate will not let me save an entity without it's relations.

How can I overcome this problem?


Solution

  • You need to define your cascades on the domain better. If you can't test it, how do you expect it will perform in the real application?

    For example:

    A -> B: Who's the owner of this relationship? Do you want to add B to A, or the other way around? This can be an implementation detail where you can have both B.SetParent(A) and A.Children.Add(B), and where you set B's parent to A in case of A.Children.Add(B) (likewise the other way around). What happens if you do:

    A a1 = new A();
    A a2 = new A();
    B b = new B();
    a1.Children.Add(b);
    b.SetParent(a);
    

    You need to make up your mind here. None of the solutions are perfect, so it's basically personal preference and app consistency that applies here.

    Working with ORMs you get into these constraint problems faster then with plain SQL (or any other datasource like XML or your own datasource), but you'd need to consider the problems if you were to write plain SQL too.

    I'm sorry, I don't have an definite answer for you, but to me it looks like you need to consider some constraints which (I presume) you haven't done yet.

    Personally, I like the repository-pattern when dealing using NHibernate in DALs. I make my repositories implement from IDisposable and let them get a session each. This way you get the "Unit of work"-pattern into your design.

    Good luck with it :)