Moq:当对象是模拟对象时,如何附加到对象的委托属性?



我有一个要测试的对象,以及我要模拟的对象的依赖项。依赖项有一个公共委托属性,其功能本质上类似于event。(我不能更改依赖项的代码。)如何模拟依赖项,然后触发其委托属性?

我的情况:


/* The thing I am mocking */
public interface IUserLoginReporter {
public delegate void UserLoggedIn(string userName);
UserLoggedIn OnUserLoggedIn { get; set; }
}

/* The thing I am testing */
public class UserService {
public UserService(IUserLoginReporter reporter) 
{
reporter.OnUserLoggedIn += RefreshLastSeenTime;
} 

public void RefreshLastSeenTime(string username)
{
...
}
}

正如你所看到的,UserLoginReporter有一个委托属性,它将在用户登录时调用该属性。UserService将它的RefreshLastSeenTime附加到这个委托上,所以我们采取一些动作作为响应。

下面是我写的测试:
[Fact]
public void DelegateGetsInvoked()
{
// Given
var mockReporter = new Mock<IUserLoginReporter>();
var userService = new UserService(mockReporter.Object);

// When
mockReporter.OnUserLoggedIn("abc");
// Then
// ... verify userService took correct actions ...
}

我在// When下面的行上得到一个空引用异常。

理想情况下,如果接口与示例中描述的一样简单,那么您最好为您的测试创建一个简单的实现。

但是,下面的代码将允许调用委托并在test

下的主题中调用附加的委托
//Arrange
var mock = new Mock<IUserLoginReporter>();
mock.SetupAllProperties(); //<--Automatically allow properties to be modifiable
UserService subject = new UserService(mock.Object);
string input = "I am working";
//Act
mock.Object.OnUserLoggedIn(input);
//Assert
mock.Verify(_ => _.OnUserLoggedIn);
//...assert expected behavior

你试图断言的内容没有被说明,所以是否可能,请拭目以待。

最新更新