Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

unit testing a factory method

suppose I have several OrderProcessors, each of them handles an order a little differently.
The decision about which OrderProcessor to use is done according to the properties of the Order object, and is done by a factory method, like so:

public IOrderProcessor CreateOrderProcessor(IOrdersRepository repository, Order order, DiscountPercentages discountPercentages)
{
    if (order.Amount > 5 && order.Unit.Price < 8)
    {
        return new DiscountOrderProcessor(repository, order, discountPercentages.FullDiscountPercentage);
    }

    if (order.Amount < 5)
    {
        // Offer a more modest discount
        return new DiscountOrderProcessor(repository, order, discountPercentages.ModestDiscountPercentage);
    }

    return new OutrageousPriceOrderProcessor(repository, order);
}

Now, my problem is that I want to verify that the returned OrderProcessor has received the correct parameters (for example- the correct discount percentage).
However, those properties are not public on the OrderProcessor entities.

How would you suggest I handle this scenario?

The only solution I was able to come up with is making the discount percentage property of the OrderProcessors public, but it seems like an overkill to do that just for the purpose of unit testing...

like image 816
J. Ed Avatar asked Oct 08 '22 11:10

J. Ed


1 Answers

One way around this is to change the fields you want to test to internal instead of private and then set the project's internals visible to the testing project. You can read about this here: http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute.aspx

You would do something like this in your AssemblyInfo.cs file:

[assembly:InternalsVisibleTo("Orders.Tests")]

Although you could argue that your unit tests should not necessarily care about the private fields of you class. Maybe it's better to pass in the values to the factory method and write unit tests for the expected result when some method (assuming Calculate() or something similar) is called on the interface.

Or another approach would be to unit test the concrete types (DiscountOrderProcessor, etc.) and confirm their return values from the public methods/properties. Then write unit tests for the factory method that it correctly returns the correct type of interface implementation.

These are the approaches I usually take when writing similar code, however there are many different ways to tackle a problem like this. I would recommend figuring out where you would get the most value in unit tests and write according to that.

like image 169
Craig MacGregor Avatar answered Oct 12 '22 11:10

Craig MacGregor