单元测试工厂方法

J. *_* Ed 5 nunit unit-testing moq

假设我有几个OrderProcessors,每个都处理一个不同的订单.
决定OrderProcessor使用哪个是根据Order对象的属性完成的,并由工厂方法完成,如下所示:

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);
}
Run Code Online (Sandbox Code Playgroud)

现在,我的问题是我想验证返回的OrderProcessor是否已收到正确的参数(例如 - 正确的折扣百分比).
但是,这些属性在OrderProcessor实体上不公开.

您如何建议我处理这种情况?

我能够提出的唯一解决方案是制作OrderProcessor公众的折扣百分比属性,但仅仅为了单元测试而这样做似乎有点过头了......

Cra*_*gor 3

解决此问题的一种方法是将要测试的字段更改为内部字段而不是私有字段,然后将项目的内部设置为对测试项目可见。您可以在这里阅读:http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute.aspx

您可以在 AssemblyInfo.cs 文件中执行以下操作:

[assembly:InternalsVisibleTo("Orders.Tests")]
Run Code Online (Sandbox Code Playgroud)

尽管您可能会说您的单元测试不一定关心您班级的私有领域。也许最好将值传递给工厂方法,并在接口上调用某些方法(假设Calculate() 或类似方法)时为预期结果编写单元测试。

或者另一种方法是对具体类型(DiscountOrderProcessor 等)进行单元测试,并从公共方法/属性中确认它们的返回值。然后为工厂方法编写单元测试,确保它正确返回接口实现的正确类型。

这些是我在编写类似代码时通常采用的方法,但是有许多不同的方法可以解决此类问题。我建议您找出在单元测试中可以获得最大价值的地方,并据此进行编写。