Moq:模拟安装过程中的奇怪参数评估

时间:2018-07-13 14:57:07

标签: c# unit-testing moq

这使我花了半天时间进行调试和调试。我正在使用Moq 4.2.1408.0717。 我有一个被嘲笑的服务。然后,我有了再次被嘲笑的客户端,但是match属性之一将使用(模拟的)服务进行评估。 简化的示例如下:

[TestFixture]
class PPAP
{
    [Test]
    public void Test_Apple_Pen()
    {
        var fruitMock = new Mock<IFruit>(); // the mocked service
        fruitMock.Setup(x => x.GetFruit()).Returns("apple");

        var fw = new FruitWrapper(fruitMock.Object); // object that uses the (mocked) service behind curtains

        var uhhMock = new Mock<IUhh>();
        uhhMock.Setup(x => x.Uhh(fw.GetFruit())).Returns("apple-pen");

        // Utterly unimportant part below, added for clarity:
        var result = uhhMock.Object.Uhh("apple");
        Assert.That(result, Is.EqualTo("apple-pen"));
    }
}

public interface IFruit
{
    string GetFruit();
}

public interface IUhh
{
    string Uhh(string s);
}

public class FruitWrapper
{
    private IFruit _fruit;

    public FruitWrapper(IFruit fruit)
    {
        _fruit = fruit;
    }

    public string GetFruit()
    {
        var f = _fruit.GetFruit(); // f should never be null since I mocked it already!
        // LOOK HERE *jumps and waves* THIS IS THE PROBLEM:
        if (f == null) {
            throw new Exception("POINT OF THE QUESTION HERE: Service mock doesn't function!!!");
        }
        return f; // yet this method will be called twice with f being null before finally called with f == "apple" during Setup()
    }
}

问题是,使用服务的代码(示例中为FruitWrapper)没有准备好从服务接收null(毕竟,这是模拟服务的关键!)。尽管如此,在客户端模拟程序的Setup()(在示例中为uhhMock)期间,将调用FruitWrapper的GetFruit(),以便服务将返回null(尽管模拟程序已经就绪)。 这是一个例外,这杀死了我的测试。我仍然不知道为什么会这样。这是正常现象还是Moq错误?

(现在,使用简化的示例,测试不会因服务失效而失效,我看到最终对match参数进行了正确评估。)编辑:修改了示例以使其不存在null从服务。如果确实如此,那么最终将有一个服务返回非空的调用。

(当然,如果我将参数(fw.GetFruit())保存到安装程序之前的变量中并在内部使用它,那一切都很好。)

编辑:由于人们难以理解我的意思。我添加了一些代码:

  • 服务返回null时抛出异常(请,请设法理解这是我的问题:该服务永远不应返回null,这是被嘲笑的!
  • 最后,进行一些不重要的验证以使测试“完整”,因为遗漏似乎激怒了人们,使他们看不到其他任何东西。注意:这不是重点。测试结果不是我的问题。

1 个答案:

答案 0 :(得分:0)

我不确定您的测试应该做什么。它是一个完整的测试吗?

<p>Click the button to create a SELECT and an OPTION element.</p>

<button onclick="createSelect()">Try it</button>

更改此项以使用您要设置的实际值:

var uhhMock = new Mock<IUhh>();
        uhhMock.Setup(x => x.Uhh(fw.GetFruit())).Returns("apple-pen");

另一个问题是,您似乎正在对多层模拟进行某种集成测试(使用模拟var uhhMock = new Mock<IUhh>(); uhhMock.Setup(x => x.Uhh("apple")).Returns("apple-pen"); 从具有模拟{{ 1}})。尝试将其分解为使用带有模拟依赖项的被测类。

一个好主意是使用AAA(排列,行为,声明)模式。例如:

IUhh