我正在尝试学习使用 Moq (4) 来测试下面的 C# 代码。我希望通过设置
mockTimer.SetupSet(m => m.Interval = It.IsInRange(
interval - shorter, interval + longer, Range.Inclusive));
在调用为间隔属性赋值的方法(ageService.AddParticipant 方法)之前,如果赋值不正确,测试将抛出。但是,即使将远超出指定范围的值分配给 AddParticipant 方法中的 Interval 属性,测试也会通过。我还发现 timer.Interval 在执行 AddParticipant 方法后的值为 0,尽管我可以看到在逐步执行 AddParticipant 方法时此属性被分配了一个非零值。
[TestMethod]
public void TestAgeUpdatingStartOnAdd()
{
var mockTimer = new Mock<IDispatcherTimer>();
mockTimer.SetupProperty(m => m.Interval);
mockTimer.Setup(m => m.Start());
mockTimer.Setup(m => m.Stop());
IDispatcherTimer timer = mockTimer.Object;
var ageService = new AgeUpdatingService(timer);
TimeSpan interval = TimeSpan.FromMinutes(10);
TimeSpan tolerance = TimeSpan.FromMilliseconds(100)
mockTimer.SetupSet(m => m.Interval = It.IsInRange(
interval - tolerance, interval + tolerance, Range.Inclusive));
ageService.AddParticipant(new Participant{ DOB = DateTime.Now + interval });
我做错了什么?我是否完全忽略了 SetupSet 方法的要点(因此应该在执行函数后坚持检查计时器对象的属性,这似乎在将 SetupSet 方法放入代码之前起作用)?如果是这样,您能否解释一下 SetupSet 的存在。谢谢。
最佳答案
由于您正在使用 new Mock<IDispatcherTimer>()
创建模拟, 它默认为 Loose
模拟行为。这意味着模拟对象在以未通过 Setup
指定的方式使用时不会提示。方法。使用接受 MockBehavior
的构造函数重载枚举和指定 Strict
将使代码表现得像你期望的那样。根据 Setup
判断,这看起来就是您期望使用它的方式电话;如果您使用松散的模拟,它们将是不必要的。
或者,您可以保留松散的模拟并更改 SetupSet
对于 Interval
成为VerifySet
在您期望它被设置之后。即:
var ageService = new AgeUpdatingService(timer);
TimeSpan interval = TimeSpan.FromMinutes(10);
TimeSpan tolerance = TimeSpan.FromMilliseconds(100)
ageService.AddParticipant(new Participant{ DOB = DateTime.Now + interval });
mockTimer.VerifySet(m => m.Interval = It.IsInRange(
interval - tolerance, interval + tolerance, Range.Inclusive));
这就像一个测试断言,意味着如果一组 Interval
调用此属性时从未发生过,它会抛出 MoqException
并未能通过测试。
关于Moq SetupSet 属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24698886/