我正在尝试使用Moq来模拟接口,但是我看不到该怎么做。界面如下所示:
public delegate void MyDelegate(int i);
public interface MyInterface
{
void Method(int i);
MyDelegate MyDelegate { set; }
}
我正在测试一个组件,该组件将带有此接口的对象作为依赖项。我希望能够在调用该方法时测试在引发委托的情况下的交互,但是我看不到该怎么做。我知道这是一种设计界面的奇怪方法,但是我对此没有控制权。
假设我有一个要测试的类:
class SystemUnderTest
{
int i = 0;
readonly MyInterface myInterface;
public SystemUnderTest(MyInterface myInterface)
{
this.myInterface = myInterface;
this.myInterface.MyDelegate = DelegateHandler;
}
public int Run(int input)
{
this.myInterface.Method(input);
return i;
}
void DelegateHandler(int i)
{
this.i = i;
}
}
我已经尝试过这样的测试,但是在设置模拟时却给出了异常。 “ ArgumentException:无法找到附加或分离方法Void set_MyDelegate(ConsoleApp1.MyDelegate)的事件。”
static void Main(string[] args)
{
// Arrange
Mock<MyInterface> mock = new Mock<MyInterface>();
mock
.Setup(m => m.Method(It.IsAny<int>()))
.Raises(m => m.MyDelegate = null, 5);
// Act
var sut = new SystemUnderTest(mock.Object);
var result = sut.Run(5);
// Assert
Trace.Assert(result == 5);
}
答案 0 :(得分:5)
您可以这么说是通过SystemUnderTest.DelegateHandler
局部变量桥接MyDelegate
。尝试这样的事情:
MyDelegate del = null;
var mock = new Mock<MyInterface>();
mock.SetupSet(m => m.MyDelegate = It.IsAny<MyDelegate>())
.Callback<MyDelegate>(d => del = d);
mock.Setup(m => m.Method(It.IsAny<int>()))
.Callback<int>(i => del.Invoke(i));
然后,实际上,每次调用SystemUnderTest.DelegateHandler
时都会调用您的mock.Method
方法。
答案 1 :(得分:2)
我认为您的方法的根本缺陷是您试图模拟代码中实际上没有发生的事情-即调用void Method(int i)
随后会调用您的委托。您不能将Raises
用于事件。
我认为您需要MyInterface
的“存根”实现,并且根本不需要使用Moq。这是我通过断言的代码:
using System.Diagnostics;
namespace ConsoleApp4
{
class Program
{
static void Main(string[] args)
{
// Arrange
var stub = new StubOfMyInterface();
// Act
var sut = new SystemUnderTest(stub);
var result = sut.Run(5);
// Assert
Trace.Assert(result == 5);
}
}
public delegate void MyDelegate(int i);
public interface MyInterface
{
void Method(int i);
MyDelegate MyDelegate { set; }
}
public class StubOfMyInterface : MyInterface
{
public void Method(int i)
{
MyDelegate?.Invoke(i);
}
public MyDelegate MyDelegate { get; set; }
}
class SystemUnderTest
{
int i = 0;
readonly MyInterface myInterface;
public SystemUnderTest(MyInterface myInterface)
{
this.myInterface = myInterface;
this.myInterface.MyDelegate = DelegateHandler;
}
public int Run(int input)
{
this.myInterface.Method(input);
return i;
}
void DelegateHandler(int i)
{
this.i = i;
}
}
}