In the previous post we learnt how we could wrap the profile system and test that we could map basic information into more complex objects. In this post we are going to use that profile wrapper as another datasource used to construct more complex and (hopefully) interesting objects.
This (slightly) more interesting object will be the so-called HybridClass, that contains information from both the profile system and another datasource.
The Coordination Service
Boring already… What can we do with this hybrid class? Not so much, but… what if we could retrieve from its persistent state and put it back to sleep when done mangling its data? Sounds like a job for some sort of service class that will deal with the profile system and that third-party datasource and that will be the star subject of our post:
Nothing to speak of, to be perfectly honest. But what if, in spite of its simplicity, we could create some tests to check that the information flows in the right direction to and from the right datasources? We could write something like this in order to check that we are hitting this another datasource in order to populate the hybrid instance:
Self confident of the simplicity of it all and expecting an straight green result, the output message can take you off-guard:
Ok, what it’s going one here? The more unit-testing-savy would have traced the scent of a “new” keyword from miles, as they know that new inside a method usually brings headaches. And that is exactly what is going on: our test is going all the way down to the inner guts of the profile system in our running program (the test suite) and found nothing like DayOfBirth defined. We have seen that one before, haven’t we?
Fixing the Test
At this stage we have to decide what to do? As I see it, two options we seem to have:
- Use the same isolation strategy used for the information not coming from the profile and hide the whole profile retrieval and persistence behind a testing-double-friendly facade.
This option is perfectly sensible and has little downsides. But it is boring enough to not deserve a post in my blog ;-)
- Roll-up your sleeves and get oneself in the middle of the profile system.
Which is several orders of magnitude more complex but likewise orders of magnitude more fun and blog post deserving :-p
We need a bit of Profile system 101 here. Basically, one defines a bunch of properties in configuration, including their types (both in runtime and persistence) and how they are going to be retrieved. The HOW is specified by a provider, which ultimately will get those properties in storage.
- “Provider, huh? That sounds extensible to me, right?”
- “Yeah. It does sound extensible”
- “Could use a custom provider for testing then?”
- “I guess you could, yeah…”
- “But that would involve messing around with configuration in our tests, right?”
- “Yeah, there has to be some configuration involved, yeah”
- “I heard that testing and configuration do not get on well, I guess we hit a dead end, right?”
- “Uhm… not really. I agree configuration and unit testing do not get on well together. But what about integration testing? We can do some of that as well, can’t we?”
Configuration in Unit Tests
So, we are going to introduce configuration for our now (officially) integration test. How do we accomplish that? As easy as creating an .config file with the sections that are needed. The only thing we have to take care of is the name of the config file, which has to be the same as of the assembly, plus .dll.config (as most of test projects are libraries) and tell Visual Studio to copy this configuration file to the output.
Once we have configuration in place we need to configure the profile system, the “what” needs to be specified, that is, define the properties we wish to persist, including their data. This is one of the parts I like the least about my solution, as we need to define (again) the properties we need to store, but since we are supposed to be testing we have already defined them! DRY anyone?
The reason I choose not to deal with is twofold:
- it is difficult as it is not a complete section (that could “externalized” into a separate file), but a piece within a section
- it does not bother me much since a change in “real configuration” would: either break existing tests or need a new set of tests to cover new properties, which will fail if test configuration is not changed
Configuration in test? tick,
What to store? tick,
How to store it? Not yet.
The reader will have to wait till next part for a custom profile provider. Until then, enjoy.