Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Moq:模拟设置期间的奇怪参数评估_C#_Unit Testing_Moq - Fatal编程技术网

C# Moq:模拟设置期间的奇怪参数评估

C# Moq:模拟设置期间的奇怪参数评估,c#,unit-testing,moq,C#,Unit Testing,Moq,这让我花了半天的时间进行调试和挠头。我用的是最小起订量4.2.1408.0717。 我有一个服务,这是嘲笑。然后我有一个客户端,它再次被模拟,但其中一个匹配属性将使用(模拟的)服务进行评估。 简化示例如下: [TestFixture] class PPAP { [Test] public void Test_Apple_Pen() { var fruitMock = new Mock<IFruit>(); // the mocked servi

这让我花了半天的时间进行调试和挠头。我用的是最小起订量4.2.1408.0717。 我有一个服务,这是嘲笑。然后我有一个客户端,它再次被模拟,但其中一个匹配属性将使用(模拟的)服务进行评估。 简化示例如下:

[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()
    }
}
[TestFixture]
类PPAP
{
[测试]
公开无效测试(苹果笔)
{
var fruitMock=new Mock();//模拟的服务
Setup(x=>x.GetFruit()).Returns(“苹果”);
var fw=new FruitWrapper(fruitMock.Object);//在幕后使用(mock)服务的对象
var uhhMock=新模拟();
设置(x=>x.Uhh(fw.GetFruit())。返回(“苹果笔”);
//为清晰起见,添加了以下完全不重要的部分:
var结果=uhMock.Object.Uhh(“苹果”);
断言(结果是.EqualTo(“苹果笔”));
}
}
公共接口IFruit
{
字符串GetFruit();
}
公共接口
{
串Uhh(串s);
}
公共类水果包装器
{
私人水果;
公共水果包装纸(IFruit水果)
{
_水果=水果;
}
公共字符串GetFruit()
{
var f=_fruit.GetFruit();//f不应该为null,因为我已经模拟了它!
//看这里*跳跃和波浪*这就是问题所在:
如果(f==null){
抛出新的异常(“这里的问题点:服务模拟不起作用!!!”;
}
return f;//但是在Setup()过程中,这个方法将被调用两次,其中f为null,最后才被调用为f==“apple”)
}
}
问题是,使用服务的代码(示例中的水果包装器)不准备从服务接收null(这毕竟是模拟服务的目的!)。尽管如此,在客户端模拟的Setup()过程中(示例中为uhmock),将调用水果包装器的GetFruit(),以便服务将返回null(尽管模拟已经就位)。 这是一个例外,扼杀了我的测试。我仍然不知道为什么会这样。这是正常的行为还是一个最小起订量错误

(现在使用简化的示例,测试不会在服务中为null时终止,我看到最后匹配参数的计算结果是正确的。)编辑:示例被修改为不在服务中为null后继续存在。如果是这样的话,最后会有一个调用,服务返回非null

(当然,如果我在设置之前将参数(fw.GetFruit())保存到一个变量中并在其中使用,那么一切都很好。)

编辑:因为人们很难理解我的意思。我添加了一些代码:

  • 如果服务返回null(请,请设法理解这是我的问题:服务永远不应该返回null,这是被嘲笑的
  • 最后进行一些不重要的验证,以使测试“完成”,因为遗漏似乎会让人非常恼火,以至于他们看不到任何其他内容。注意:这不是重点。测试结果不是我的问题

我不确定你的测试应该做什么。这是一个完整的测试吗

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

无意中按下Enter键,现在超过5分钟过去了。不,这当然不是一个完整的测试,只是为了(对我来说)演示Setup()关于模拟服务的复杂行为。是的,这可能更像是一个集成测试,而不是单元测试。在真实场景中,有一个文件系统模拟(~uhmock)这用于测试一些复杂的项目加载过程。但这不是重点。我主要关心的是Setup()期间的参数计算,它似乎忽略了以前的模拟(至少暂时忽略)。不,到那时服务已经被模拟。如果我在Setup()之前将fw.GetFruit()的结果保存到变量中调用,并在设置中使用该变量,则一切正常。“我主要关心的是Setup()期间的参数计算,它似乎忽略了以前的模拟”它只保留最后的设置。如果您想以不同的方式模拟多个调用,请使用
SetupSequence
。我认为您删除了太多的真实代码,因此您的问题无法重现。请小心lambda中具有不同参数名称的多个设置,因为它们是不同的表达式。此时将对fw.GetFruit()进行求值"-不,它不会。它只是一个
表达式
用于在
设置
中注册。它不会在
设置
@GeorgeHelyar期间执行。不,这不是我的意思。两个不同的东西是模拟的,上面没有相同模拟的顺序设置。我知道你得到了什么,这个问题适用于你想要的任何设置o在该对象上,不仅仅是方法调用;在Moq 4.9.0(即最新版本)中也是如此。作为记录,我不会执行
uhmock.Setup(x=>x.Uhh(fw.GetFruit())
,因为
fw.GetFruit()的结果
已经在测试的前面设置好了:我将使用一个常量作为返回值,并且在这个设置中也使用该常量,因为它使测试更容易阅读。
var uhhMock = new Mock<IUhh>();
            uhhMock.Setup(x => x.Uhh("apple")).Returns("apple-pen");
[Test]
public void Test_Apple_Pen()
{
    //Arrange
    var fruitMock = new Mock<IFruit>(); 
    fruitMock.Setup(x => x.GetFruit()).Returns("apple");

    var fw = new FruitWrapper(fruitMock.Object);

    //Act
    var result = fw.GetFruit();

    //Assert
    Assert.AreEqual("apple", result);
}