views:

49

answers:

3

The project that I have just joined uses the command pattern quite extensively for handling calls into the business logic layers of the project.

The business logic layers are built as static handlers calling into providers. The commands then call into these static handlers.

The team want to improve test coverage, and I would like us to move more toward true TDD but the use of static handlers means that there is a hard coded dependency in the commands and there is no way to inject the handlers as dependencies and so it is very difficult to unit test the commands in isolation.

Does anyone have any good suggestions for a strategy for us to move toward a more testable command pattern bearing in mind that there are a lot of commands already in use.

The process method below would be called when execute is called on the command. This would be the method under test. This is a typical example of the usage of static handlers in the command classes.

protected override bool Process()
{
    this.user = SecurityHandler.ActivateUser(this.activationGuid);
    bool success = this.user != null;

    if (!success)
    {
        this.AddStatusMessage(StatusMessageType.Error, "/Commands/Security/ActivateUserCommand/IncorrectLink", true);
    }

    return success;
}
+1  A: 

Dependecy Injection (Inversion of control)

Static dependencies are bad smell, and usually one can use DI/IoC to remove that bad smell. Find any DI/IoC framework you like and use it.

nanda
Hi nanda, yes it is clear that DI is the way to go, but as I said there are a lot of commands already in play, so ideally we would not want to have to refactor each of these. Obviously we may have to, but I was wondering if anyone here may know of a way that we might do this without refactoring all of the commands.
Jet Basrawi
The good news of DI framework is that it's doesn't force you to use it everywhere. Refactor a little and deploy. Next time do the next refactor and move on.
nanda
I think then your answer is to go the hard way, but in small easy steps. I think ultimately this may have to be the way to do it.
Jet Basrawi
+2  A: 

Static methods/fields generally hurt with testability - because it introduces the risk of tests not being isolated. One test could set some static field, changing the initial state for test2.

That said there was nothing in the Command Pattern that needed static handlers.. so I think it's a custom implementation. I would like to see some sample code for a shorter answer.

There is no easy way out.. move the static parts into another class/object and pass it into the objects that need to access it. This might mean adding a parameter to methods that are currently using a TypeName.StaticField invocation to get at the data.

Update (for posted code snippet): I fail to see the Command Pattern here.. anyways to get the method under test.

  • Does the SecurityHandler.ActivateUser have any side-effects ? Does calling it the second time differ in any manner from calling it the first time? If not (i.e. it is a pure service call) then dont worry about it.
  • if ActivateUser has some side-effects, then you have to do some work. i.e. Turn the static methods into instance methods and pass in an instance of SecurityHandler to the containing type of Process(). You can either pass it in as a method parameter to Process() or a ctor/property set on containing type. Choose whatever you feel is apt.
Gishu
The code snippet shown is only the process method that is called when execute is called on the base command. This is not the whole command class, this snippet is effectively the execute method of the command class
Jet Basrawi
In this case, the handler returns a user, but there are many different cases that all have different effects. I would ultimately want to pass in the handler and verify that the appropriate method has been called with the appropriate parameters, so your part 2 edit is what will have to happen. I am going to investigate the possibility of Typemock today as suggested by Grant to see if that is a possibility but as he says it will never be an ideal soluion and refactoring to inject the dependency is still looking like the best solution.
Jet Basrawi
@Jet - Ok. Makes sense now... My recommendation then would be to pass in the handler as a ctor parameter to the specific Command subclasses.
Gishu
A: 

Although this doesn't help in terms of design patterns, if you want to increase testing now you could always use something like Typemock Isolator or Telerik JustMock, which allow you to mock out static classes, while you convert your code away from the current design. (These are commercial products).

I wouldn't do that myself though, as there's a danger you'll just start relying on them and not bother refactoring your code to make it testable - one of the things I like about TDD/automated testing is that it forces you to have code which is loosely coupled and follows some good design principles, and tools like these can take away from that.

Grant Crofton
Thanks Grant, will be exploring the possibility of using Typemock today.
Jet Basrawi
When I say 'I wouldn't do that myself', what I really mean is I wouldn't do that unless there was no better alternative. Certainly better to use these tools than not to unit test at all!
Grant Crofton