Home > Development > Unit Testing And Factory Pattern

Unit Testing And Factory Pattern


I had a comment the other day on how a factory method / abstract factory object may increase coupling and not allow unit testing. Basically the idea was then to use dependency injection for the factory.

You do not have to do this you can use this technique I learnt from “The art of unit testing book” by Roy Osherove.

public static class TaxationCalculatorFactory
    {

        private static ITaxationCalculator calculator = null;

        private static void InitializeForTest(ITaxationCalculator calc)
        {
            calculator = calc;
        }

        public static ITaxationCalculator GetCalculator(string location)
        {

            if (calculator != null)
                return calculator;

            switch (location)
            {
                case "Australia":
                    return new AustralianTaxCalculator();
                case "British":
                    return new BritishTaxCalculator();
                default:
                    throw new ArgumentException("Invalid Location");
            }
        }
    }

    public interface ITaxationCalculator
    {
        decimal CalculateTaxPayable(decimal salary);
    }

Basically this would allow you to assign a mock / stub for the purpose of testing.

Blair…

Advertisements
  1. scottg
    March 1, 2010 at 4:05 pm

    Hey Blair- doesn’t this violate OCP? When new TaxCalculators are added, you need to modify the switch block in this factory – hence the suggestion of injecting available calculators during app start up. I’m not sure about the new InitializeForTest method – it doesn’t add any ‘business’ value.

  2. March 2, 2010 at 1:24 am

    No it does not violate open closed principle. You ONLY call the method and assign it a stub / mock if you need to control code under test.

  3. scottg
    March 2, 2010 at 1:52 pm

    Take the testing scenario out for a moment… The switch block in the factory class is not ‘closed for modification’, when a new country is added, an additional case is necessary – perhaps I am over-engineering this 🙂

  4. March 2, 2010 at 2:07 pm

    There does come a point where at some stage you can not escape this sort of stuff. There is no such thing as a perfect world 🙂

    If there is no logic at all there is no application. At least the factory hides it 🙂

  5. Mark Hillary
    April 3, 2010 at 6:50 pm

    Maybe I’m missing something here but what is the point of this?

    You have added extra logic to allow you to inject a mock into your factory, but all this will test is that logic you’ve added works. You’re not testing anything else about the factory other than the extra logic. So it seems completely self defeating.

    Factories are by there nature integration code so really should be tested as part of an integration test suite. There doesn’t seem to be any value in unit testing something that’s sole job is to create concrete objects.

    • February 23, 2011 at 9:13 am

      Mark,

      I believe the point here is not about testing the factory. The point is about testing the code using the ITaxationCalculator and relying on the factory to provide a concrete implementation.

      What this code should allow you to do is to use a mock implementation of the ITaxationCalculator interface injecting it into the factory via the InitializeForTest() method.

      That being said, I am not sure how that might be achieved since the InitializeForTest is marked as private.

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: