我有一个通过事件驱动的异步模式公开异步操作的服务。
public interface IService
{
void DoAsync(int param);
event DoCompleted;
}
还有另一个类依赖于IService服务对象
public class Foo
{
private IService _service;
public EventHandler CalculationComplete;
public void Foo(IService service) {_service = service};
public int Calculated;
public void CalculateAsync(int param)
{
//Invoke _service.DoAsync(param)
//(...)
}
}
基本上在调用foo之后.CalculateAsyc CalculationComplete应通知消费者计算完成。
问题是如何在单元测试Foo时模拟IService?我正在使用Moq。更具体地说,如何使unittest等待CalculationComplete事件并做出相应的反应?
答案 0 :(得分:6)
很难知道你要在这里测试什么,所以我不能给你一个100%准确的样本。您的示例代码似乎缺少了一些细节......我填写了一些遗漏的内容,但还有更多问题。
在任何情况下,我用来等待事件的方法都是信号量。我喜欢在这样的简单场合使用AutoResetEvent。
public class Foo
{
private IService _service;
public EventHandler CalculationComplete;
public Foo(IService service)
{
_service = service;
_service.DoCompleted += (o,e) =>
{
Calculated = e.Result;
if(CalculationComplete != null) { CalculationComplete(this, new EventArgs()); }
};
}
public int Calculated;
public void CalculateAsync(int param)
{
_service.DoAsync(param);
}
}
public interface IService
{
void DoAsync(int param);
event EventHandler<DoResultEventArgs> DoCompleted;
}
public class DoResultEventArgs : EventArgs
{
public int Result { get; set; }
}
[TestMethod]
public void CalculateAsync_CallsService_CalculatedIsPopulated()
{
//Arrange
Mock<IService> sMock = new Mock<IService>();
sMock.Setup(s => s.DoAsync(It.IsAny<int>()))
.Raises(s => s.DoCompleted += null, new DoResultEventArgs() { Result = 324 });
Foo foo = new Foo(sMock.Object);
AutoResetEvent waitHandle = new AutoResetEvent(false);
foo.CalculationComplete += (o,e) => waitHandle.Set();
//Act
foo.CalculateAsync(12);
waitHandle.WaitOne();
//Assert
Assert.IsEqual(foo.Calculated, 324);
}
如果没有更多信息,这是我能做的最好的事情。我希望这就是你要找的东西。