Refactoring: parameterize constructor
In legacy code you may find classes with constructor where some objects are created and initialized. These classes are not easily testable because they depend on other classes and therefore when you unit test these classes they may also throw exceptions of classes they depend on. In these cases we can use parameterize constructor refactoring.
Let’s look at the following class.
public class MassMailer
{
private Mailer _mailer;
public MassMailer()
{
_mailer = new Mailer();
}
// other methods follow here
}
We can see that in the constructor of this class the Mailer object is created and initialized. If we want to unit test this class we have to remove this dependency. It is possible that we cannot go to interfaces but at least we can use “safe” copy of Mailer class for testing purposes. Maybe we can extend this class and override some methods with our dummy methods so mailer doesn’t affect our tests.
Let’s add new constructor to our class. New constructor accepts one parameter – the mailer object.
public MassMailer(Mailer mailer)
{
_mailer = mailer;
}
Why don’t we change current constructor? The point simple – we may break current working code this way. It is good to have only one point where class is initialized, so let’s modify current constructor so it works safe.
public MassMailer()
{
MassMailer(new Mailer());
}
Now we have made MassMailer class independent of Mailer class if we use our new constructor. Of course we still have dependency but this dependency is for backward compatibility. In other means our class is now testable.
I like doing things like this with constructor chaining…
(Mailer implements IMailer)
public class MassMailer
{
private IMailer mailer;
public MassMailer():this(new Mailer()){}
public MassMailer(IMailer mailer)
{
this.mailer = mailer;
}
}
Congratulations…you’ve discovered Constructors!