【发布时间】:2019-02-17 09:33:18
【问题描述】:
我拥有的是来自外部库(本例是 WebSocketSharp)的类的包装器,包装器类对某些事件做出反应,例如建立连接时等。
为了测试这个包装类,我模拟了 WebSocket 类并在该类上做了 Raise.EventWith,我希望 Wrapper 类能够处理它应该做的事情。
代码是这样的:
public class WebsocketClient {
public event EventHandler Connected;
public WebSocket Connection { get;set; }
public void ConnectAsync() {
Connection.OnOpen += Connection_OnOpen;
Connection.ConnectAsync();
}
private void Connection_OnOpen(object sender, System.EventArgs e) {
Connected?.Invoke(this, new EventArgs());
}
}
我想写的测试是:
public void ConnectedTest() {
var objClient = new WebsocketClient();
var raised = false;
objClient.Connected += delegate (object sender, EventArgs e) {
raised = true;
};
var objWebSocket = Substitute.For<WebSocketSharp.WebSocket>("wss://localhost:443");
objClient.Connection = objWebSocket;
objClient.ConnectAsync();
objClient.Connection.OnOpen += Raise.EventWith(new object(), new EventArgs());
objWebSocket.Received().OnOpen += Arg.Any<EventHandler>();
Assert.IsTrue(raised);
}
显然,事情被简化了一点,因为还有一些事情需要检查,这只是为了让大家了解这个想法。
在测试中,我想验证两件事,即当调用 ConnectAsync 时,会将事件处理程序添加到 OnOpen 事件中,并且当触发 OnOpen 时,我会从正在测试的类中返回一个事件。
我知道的反应是,这是“糟糕的设计”,但这对我没有多大帮助,你将如何解决这个问题?,我需要包装 WebSocket 类,这不是我的所以有没有发言权。
在这种情况下,我唯一能想到的是扩展 WebSocket 类而不是制作包装器,但我确信我需要进行其他测试,其中扩展不是一种选择,并且编写这样的包装器会需要,例如,当使用事件处理程序是私有的文件系统观察器或计时器时,仍想测试事件被触发时会发生什么。
为了演示,例如如何测试这个? (没有跑任何东西,只是为了展示想法)
public class FilesDeleted {
private FileSystemWatcher _objWatcher;
private List<string> _lstPaths;
public event EventHandler ItemsDeleted;
public FilesDeleted(string pPath) {
_lstPaths = new List<string>();
_objWatcher = new FileSystemWatcher(pPath);
}
public void Start() {
_objWatcher.Deleted += _objWatcher_Deleted;
_objWatcher.EnableRaisingEvents = true;
}
private void _objWatcher_Deleted(object sender, FileSystemEventArgs e) {
_lstPaths.Add(e.FullPath);
if(_lstPaths.Count > 10) {
ItemsDeleted?.Invoke(this, new EventArgs());
}
}
}
在测试中,您想要验证在文件系统观察器中的 10 个文件删除事件之后,您会从此类中获得“ItemsDeleted”事件。
认为 FileSystemWatcher 示例显示了我最苦恼的问题
【问题讨论】:
标签: c# testing mocking nunit nsubstitute