FakeItEasy:不使用简单的Fake

时间:2018-11-09 12:35:11

标签: c# fakeiteasy

我正在尝试使用FakeItEasy(版本4.9.1)为某些旧代码创建单元测试。我已经创建了两个单元测试,其中一个可以按预期工作,而另一个非常相似,尽管经过反复试验,仍然无法正常工作。

以下是该方法的摘录,似乎无法测试:

public class PosMessageProcessor : IPosMessageProcessor
{
    public void Execute()
    {
        PurchaseOrderRepository repo = new PurchaseOrderRepository();
        ...
        try
        {
            m_PurchaseOrder = GetOrderForProcessing(repo);
            ...

这是我的测试:

[TestMethod]
[TestCategory("POS")]
public void ExecuteTest()
{
    // Arrange
    PurchaseOrder purchaseOrder = GetPurchaseOrder();
    IPosMessageProcessor fakePosMessageProcessor = A.Fake<IPosMessageProcessor>();
    A.CallTo(() => fakePosMessageProcessor.GetOrderForProcessing(A<IPurchaseOrderRepository>.Ignored)).Returns(purchaseOrder);

    // Act
    _posMessageProcessor.Execute();

    // Assert
    A.CallTo(() => fakePosMessageProcessor.GetOrderForProcessing(A<IPurchaseOrderRepository>.Ignored)).MustHaveHappened();
}

_posMessageProcessor变量是PosMessageProcessor类的实例。我想捕获对GetOrderForProcessing()方法的调用(在Execute()方法内),并使其返回我的硬编码purchaseOrder对象。但是我得到了另一个返回值(null)。为什么?

有效的单元测试将测试GetOrderForProcessing()方法:

[TestMethod]
[TestCategory("POS")]
public void GetOrderForProcessingTest()
{
    // Arrange
    PurchaseOrder purchaseOrder = GetPurchaseOrder();
    IPurchaseOrderRepository fakePurchaseOrderRepository = A.Fake<IPurchaseOrderRepository>();
    A.CallTo(() => fakePurchaseOrderRepository.GetPurchaseOrderByOrderTrackingNumber(A<string>.Ignored)).Returns(purchaseOrder);

    // Act
    PurchaseOrder result = _posMessageProcessor.GetOrderForProcessing(fakePurchaseOrderRepository);

    // Assert
    A.CallTo(() => fakePurchaseOrderRepository.GetPurchaseOrderByOrderTrackingNumber(A<string>.Ignored)).MustHaveHappened();
    Assert.IsNotNull(result);
}

在这种情况下,对GetPurchaseOrderByOrderTrackingNumber()的调用将按预期返回我的硬编码对象。这两个测试实际上是相同的,除了GetOrderForProcessing()方法接受一个参数而Execute()不接受参数。

1 个答案:

答案 0 :(得分:1)

ExecuteTest失败,因为您配置了伪造的IPosMessageProcessor,然后在真实的ExecutePosMessageProcessor上调用_posMessageProcessor_posMessageProcessor是实际的PosMessageProcessor,将执行其常规代码路径,并调用实际的Execute,而实际的GetOrderForProcessing将调用实际的fakePosMessageProcessor

(请注意,您实际上可以从测试中删除GetOrderForProcessing变量及其所有引用,其行为将是相同的。)

我不推荐这种测试,但是为了伪造Execute并仍然测试实际的public void NewExecuteTest() { // Arrange PurchaseOrder purchaseOrder = GetPurchaseOrder(); // Get a fake PosMessageProcessor that falls back to original behaviour for all calls. IPosMessageProcessor fakePosMessageProcessor = A.Fake<PosMessageProcessor>(options => options.CallsBaseMethods()); // Now fake out the GetOrderForProcessing call so we can test Execute. A.CallTo(() => fakePosMessageProcessor.GetOrderForProcessing(A<IPurchaseOrderRepository>.Ignored)).Returns(purchaseOrder); // Act fakePosMessageProcessor.Execute(); // Assert A.CallTo(() => fakePosMessageProcessor.GetOrderForProcessing(A<IPurchaseOrderRepository>.Ignored)).MustHaveHappened(); } 代码,您必须编写类似的测试

nineteen=year[year>=60]+1900
twenty=year[year<60]+2000
year=c(nineteen,twenty)