views:

104

answers:

4

We have recently adopted the specification patterns for validating domain objects and now want to introduce unit testing of our domain objects to improve code quality.

One problem I have found is how best to unit test the validate functionality shown in the example below. The specification hits the database so I want to be able to mock it but as it is instantiated in-line I can't do this. I could work off interfaces but this increases the complexity of the code and as we may have a lot of specifications we will ultimately have a lot of interfaces (remember we are introducing unit testing and don't want to give anyone an excuse to shoot it down).

Given this scenario how would we best solve the problem of unit testing the specification pattern in our domain objects?

...
public void Validate()
{
    if(DuplicateUsername())
    { throw new ValidationException(); }
}

public bool DuplicateUsername()
{
    var spec = new DuplicateUsernameSpecification();
    return spec.IsSatisfiedBy(this);
}
+1  A: 

You could extract getDuplicateUsernameSpecification() into a public method of its own, then subclass and override that for your tests.

Carl Manaster
That is a good idea, we were thinking of overriding the domain object and overriding the DuplicateUsername method but it just doesn't sit well with me.
Burt
+4  A: 

A more gentle introduction of Seams into the application could be achieved by making core methods virtual. This means that you would be able to use the Extract and Override technique for unit testing.

In greenfield development I find this technique suboptimal because there are better alternatives available, but it's a good way to retrofit testability to already existing code.

As an example, you write that your Specification hits the database. Within that implementaiton, you could extract that part of the specification to a Factory Method that you can then override in your unit tests.

In general, the book Working Effectively with Legacy Code provides much valuable guidance on how to make code testable.

Mark Seemann
Thanks for the feedback Mark, I agree with everything you say but was hoping for a decent solution to this. There is something that doesn't sit well about inheriting classes and overriding methods in the test project, I think it would be overhead that we could avoid if we came up with a decent design in the first place, which is what I am hoping to get out of this post.
Burt
@Burt: I may have misunderstood your question then. 'Decent' design revolves around SOLID. Particularly the Open/Closed Principle is very important for testability. That again involves DI, which means lots of interfaces and Abstract Factories, and I read your question to the effect that you couldn't really afford that tax right now.
Mark Seemann
I didn't want to rock the boat too much but it loks like interfaces will be the best way to achieve what I want.
Burt
Using interfaces is definitely the best long-term strategy because it fits better into the "favor composition over inheritance" philosophy.
Mark Seemann
+1  A: 

If you use IoC then you can resolve the DuplicateUsernameSpecification and in test mockup the last one

Edit: The idea is to replace direct constructor call with factory method. Something like this:

public bool DuplicateUsername()
{
    var spec = MyIocContainer.Resolve<DuplicateUsernameSpecification>();
    return spec.IsSatisfiedBy(this);
}
dh
Using an IoC container as a Service Locator is generally not considered best practice. You're much better off using constructor injection. You can still use a container, but that only needs to be surfaced in (or coupled to) one place in your application.
TrueWill
I thought about this and tried to implement it, can I mock up a concrete class without an interface using mocking frameworks i.e. MOQ?
Burt
I think it won't be possible to mock a method which is not virtual, so if a generalization could be possible for validation with interface like ISpecification { bool IsSatisfiedBy<T>(T target); } that could work.
dh
2TrueWill: the realization could be either Service Locator or any kind of DI, the idea is still to replace direct constructor call which is hardly mockable
dh
+2  A: 

If you dont want to do constructor injection of a factory, and make the specs mockable... Have you considered TypeMock? It is very powerful for dealing with this sort of thing. You can tell it to mock the next object of type X that is to be created, and it can mock anything, no virtuals etc required.

DW