1

I often come across situations were I want to save the content of a large object graph (run-time or during debugging) to a set of statements recreating this object graph. This can then be used as test data in unit test cases.

screenshot of debugger

Taken that leafs of the object graph are standard types (String, BigDecimal, Date, etc) and the branches follow the bean convention (getters, setters, empty constructor), it should be possible to generate this kind of file (e.g. TestData.java):

   public static Car createCar() {

    Wheel wheel1 = new Wheel();
    wheel1.setTypePressure( 2.1f );
    Wheel wheel2 = new Wheel();
    wheel2.setTypePressure( 2.3f );
    Wheel wheel3 = new Wheel();
    wheel3.setTypePressure( 2.0f );
    Wheel wheel4 = new Wheel();
    wheel4.setTypePressure( 2.8f );
    List<Wheel> wheels = new ArrayList<>( Arrays.asList( wheel1, wheel2, wheel3, wheel4 ) );

    Brake brake = new Brake();
    brake.setBrakeType( BrakeType.PLAIN );

    Car car = new Car();
    car.setBrake( brake );
    car.setWheels( wheels );
    car.setColor( "blue" );

    return car;
}

It would be really great to plug this directly into a debug session somehow, but a few drop-in statements writing as result the "java object graph creation code with content" output to System.out would also work.

So, how can I realize this in the most efficient way?

Sjaak
  • 3,602
  • 17
  • 29

3 Answers3

2

Nice idea, but (probably opinionated) not the best solution.

Yes, that data could be transformed into a Java program; which then needs to be saved, compiled, ...

Then questions arise such as: do you want to keep source code around, or compiled code; what about versioning (of data, or the underlying JRE)?

Long story short: Java code isn't a very convenient format to represent data. Thus: instead of turning your data into Java code, turn it into some JSON representation for example.

The point is: when your classes are really following "bean style"; and they already have getters/setters/default constructors - then any decent JSON parser library should work "out of the box". You throw your Car object at it; and out comes nice, standard JSON. Then you write a little helper tool that reads such files and turns them back into Car objects. Done.

That is the way to go (and this advise comes from somebody who worked on a system where the architect wanted exactly that what you are asking for; and we spent a lot of time and pain to get there ... but that was more than 10 years ago; and in 2017 you simply don't do that any more).

Given your latest comment (as you are mainly interested in unit testcode); I would suggest to look into using the builder pattern here.

So that your code would boil down to

new CarBuilder().wheel(new WheelBuilder(). ...

The nice thing about that: there are various ways to generate such builders for you; for example project Lombok has a @Builder annotation!

In any case, the market for generating builders automatically is pretty rich!

Community
  • 1
  • 1
GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • I concur. I also propose dropping a simple example of, say, GSON at work. It is incredible what you can do with a one-liner, and it will probably convince OP more than just stating that it is easy. – tucuxi Feb 08 '17 at 08:15
  • If there's no out-of-the-box solution I will try JSON. My only concern is that data kept in a seperate JSON file from your (Junit) test code is not subjected to refactoring. Ergo: if my model changes (attribute names, entity names) refactor will automatically tackle the java solution. Admit: if the structure changes I'll have a problem anyway. – Sjaak Feb 08 '17 at 20:11
  • @tucuxi. I just tried on my small example. It is indeed amazing. – Sjaak Feb 08 '17 at 20:47
  • @sjaak After some more thinking, and your updates; I put up another update for you. Feel free to accept/upvote if that matches your needs better ;-) – GhostCat Feb 09 '17 at 07:39
  • @GhostCat: I started to play around with using JSON as you initially suggested. Thanks for that suggestion. I think that's the way to go (and feels pretty lean). I'm familiar with Lombok, builder patterns and / or object mother. I did not know however Lombok provided builders-out-of-the box :). Worthwhile to take a shot at it. But first: json :) – Sjaak Feb 09 '17 at 20:17
0

I'm not aware of any IDE plugin that would do that, and I couldn't find one by Googling. In the absence of an existing plugin (for your IDE) written by someone else, the answer to your question:

How can I realize this in the most efficient way?

depends on whether it is more efficient to develop the plugin (yourself!) or just continue with writing the test cases by hand.

My guess is that the latter will be more efficient.


Also I agree with @GhostCat's. If your testcases are "data intensive", it would be better to choose / implement a text-based serial format for the test data, and express the test data that way. In my experience, it is easier to read / modify test data expressed that way than test data that is coded as a bunch of Java calls to construct object graphs. It is important that your test cases are not "write only".

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
0

I'd look at persisting your graph to some human-readable, yet parsable form. XML may be your best choice as the syntax allows for cross-document references, but any format would work - even a custom syntax. This would let you persist and transmit graphs at runtime while supporting easy-to-modify and -replicate test graphs for unit tests.

Chris Gerken
  • 16,221
  • 6
  • 44
  • 59