How to preserve an in memory datastructure to later use it in a Unit test
Asked Answered
A

2

5

In my code, I am occasionally passed various byte arrays and such. Also, they may be managed objects. I would like to preserve those memory structures so that I can write test cases against the concrete examples.

My standard approach is to hit the breakpoint, use the debugger to find the various values and then either new them up or embed a file or something in the unit test assembly as a resource. Sometimes, this involves writing my own abstraction of the component interaction to make my code depending on something that can be new'ed up.

Is there an easier way? I cannot imagine that this is something new. Let's say that you are given a fire central unit to communicate with. You play around with it to make it produce its datagrams, which you want to create for your unit tests. Also, when you encounter a bug due to some undocumented way that the fire central is composing its composite messages, you want to record and preserve those examples.

Ideally, I would like to be able to record all interaction to my code and then pick and choose various playback scenarios. But just getting the various datagram examples in-memory from the debugger and put it back into a unit test would help me a lot.

Any suggestions?

Apeldoorn answered 29/9, 2009 at 7:49 Comment(0)
P
4

Try with binary serialization.

The above is specifically for the part where you want to save/load the info or some objects holding info that you use to test the interaction with that external system. I prefer to call those tests focused integration tests, to better capture the difference of focus from the unit tests of the rest of your code with other logic you may have.

Try to separate the code that does the specific integration with the external system from the rest of the code in your system. I suggest to put it behind an interface, that you can replace/mock when creating your unit tests for the rest of the system. This way you can have specifically crafted scenarios that test several aspects/logic of your code without hitting the external system - which also means you can run lots of them in seconds.

Pepys answered 29/9, 2009 at 7:59 Comment(3)
+1 Not a bad suggestion, but it does require that the types in question are serializableCondensation
@Mark y, that was really meant more for the part where he talks on saving/loading the requests/responses he exchanges with the external system - so I am thinking simple objects. I wouldn't recommend going to the rest of the tests with the same approach.Pepys
Indeed. I will not allow communication details to manifest themselves within the service layer. I have specific business entities (class libraries) that deal with the communication details, and these are their tests. There is an abstraction layer between the communication and the business logic. Thank you.Apeldoorn
C
3

As Freddy Rios hints in his answer, you need some way of persisting the in-memory object so that you can reuse it from your unit tests. The Memento design pattern is a good start, and serialization is the default .NET way of implementing it.

That leaves the question on how to easily capture those objects. Here's an approach that you can try:

Abstract the communication to and from your resource behind an interface. That is always a good design decision.

When you do that, you can use the Decorator design pattern to wrap your real implementation of that interface. This means that you can create a Decorator that simply records (serializes) the interaction, but delegates all calls to an underlying implementation after it has recorded the objects in question.

When you troubleshoot, you can hook your code up to the Memento Decorator and later pick up the files whereever they where written. For production code, you simply skip the Memento Decorator and directly use the real implementation.

If you want to be really fancy, you can even implement the Memento Decorator so that it emits unit test code that mimics the interaction that was recorded, but this is likely to require a fair amount of effort...

Condensation answered 29/9, 2009 at 8:14 Comment(2)
The decorator idea may have some merit. Though I am not sure wether or not the decorator will be able to access the knowledge necessary to discern wether the communicated blob was interesting or not. But it could be a nice way to make sure that the original datagram is intact as part of an error message payload. And it would be simple to enable/disable it through configuration. Thank you.Apeldoorn
@Tormod: You are right about the question about evaluating whether the blob was interesting or not. Either you simply record everything and then delete stuff according to some expiry policy, or you would need to implement some kind of heuristic to determine whether to record or not. As I don't know the details of your environment, I don't have a particular solution for that.Condensation

© 2022 - 2024 — McMap. All rights reserved.