使用Moq模拟Fluent接口

问题描述 投票:0回答:1

我已经在此问题上查看了许多问题,但似乎都没有解决我遇到的问题。

我有看起来像这样的代码...

IBaseDataCollector<MyClass> myDataCollector;

myDataCollector = new Mock<IBaseDataCollector<MyClass>>();

systemUnderTest = new Thing(myDataCollector.Object);

并且在我的Thing类中...

var collection = myDataCollector.SomeMethod()
                     .SomeSecondMethod()
                     .GetData();

SomeMethod()SomeSecondMethod()都返回this(即,myDataCollector的实例)

[运行测试时,我在调用NullReferenceException的地方得到一个myDataCollector

我尝试在我的测试设置中添加它...

myDataCollector.Setup(_=> _.SomeMethod()),Returns(myDataCollector.Object);

但是它甚至无法编译,抱怨它“无法解析方法'Returns(IBaseDataCollector)'”]

现在,如果我将我的Thing类重构为可读的...

myDataCollector.SomeMethod();
myDataCollector.SomeSecondMethod()
var collection = myDataCollector.GetData();

我的测试正常执行。

如果是这样,我只是重构代码并继续生活,但实际上,我需要在SelectMany调用中调用我的代码...

var collection = list.SelectMany(_=> myDataCollector.SomeMethod()
                     .SomeSecondMethod(_)
                     .GetData());

同样,我知道我可以SelectMany代替ForEach,并使用对GetData()的每次调用的结果手动填充集合,以便摆脱调用的流利元素,但这意味着重构代码只是为了使测试正常进行,这感觉是错误的。

我应该如何在模拟对象上调用Setup()以使流利的调用正常工作?

c# unit-testing moq fluent
1个回答
0
投票

请看下面的测试代码(我发明了一些细节来填补空白)。如图所示,模拟对象实例应该可以作为从其自身方法返回的值。

    public class UnitTestExample
    {

        [Fact]
        public void UnitTestExample1()
        {
            var myClassInterfaceMock = new Mock<IInterface<MyClass>>();
            var instance = myClassInterfaceMock.Object;
            var myList = new List<MyClass>()
            {
                new MyClass() { Attribute = 1 }
            };

            myClassInterfaceMock.Setup(_ => _.SomeMethod()).Returns(instance);
            myClassInterfaceMock.Setup(_ => _.SomeSecondMethod()).Returns(instance);
            myClassInterfaceMock.Setup(_ => _.GetData()).Returns(myList);

            var myDependentClass = new MyDependentClass(instance);
            var result = myDependentClass.DoTheThing();

            Assert.True(result.Count.Equals(1));
        }
    }

    public interface IInterface<T>
    {
        IInterface<T> SomeMethod();
        IInterface<T> SomeSecondMethod();
        List<T> GetData();
    }

    public class MyClass
    {
        public int Attribute { get; set; }
    }

    public class MyDependentClass
    {
        private readonly IInterface<MyClass> _test;

        public MyDependentClass(IInterface<MyClass> test)
        {
            _test = test;
        }

        public List<MyClass> DoTheThing()
        {
            return _test.SomeMethod().SomeSecondMethod().GetData();
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.