我已经在此问题上查看了许多问题,但似乎都没有解决我遇到的问题。
我有看起来像这样的代码...
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()
以使流利的调用正常工作?
请看下面的测试代码(我发明了一些细节来填补空白)。如图所示,模拟对象实例应该可以作为从其自身方法返回的值。
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();
}
}