c# - 如何测试事件处理程序的结果
问题描述
我有一个 ViewModel,它在构造函数中接收带有事件处理程序的接口:
public VehiclesViewModel(IVehicles vehicles)
{
_vehicles = vehicles;
VehicleRows = new ObservableCollection<VehicleRowViewModel>();
_vehicles.ListVehicles("secret", callback);
}
回调将所有列出的车辆添加到 ObservableCollection 中:
private void callback(object sender, MyAsyncCompletedEventArgs e)
{
if (e.Result is Vehicle[] vehicles)
{
foreach (var vehicle in vehicles)
{
VehicleRows.Add(new VehicleRowViewModel {Name = vehicle.Name});
}
}
}
public ObservableCollection<VehicleRowViewModel> VehicleRows { get; set; }
Vehicle 和 VehicleRowViewModels 只是简单的类:
public class VehicleRowViewModel
{
public string Name { get; set; }
}
public class Vehicle
{
public string Name { get; set; }
}
这是代码的其余部分:
public interface IVehicles
{
void ListVehicles(string category, MyAsyncCompletedEventHandler callback);
}
public delegate void MyAsyncCompletedEventHandler(object sender, MyAsyncCompletedEventArgs e);
public class MyAsyncCompletedEventArgs : AsyncCompletedEventArgs
{
public MyAsyncCompletedEventArgs(Exception ex) : base(ex, true, null)
{
}
public object Result { get; set; }
}
现在我想测试车辆数量是否正确添加到 VehicleRows 中:
[TestFixture]
public class VehiclesViewModelTests
{
[Test]
public void AllVehiclesFromCallBackEndUpInProperty()
{
var vehiclesMock = new Mock<IVehicles>();
vehiclesMock.Setup(x => x.ListVehicles(It.IsAny<string>(), It.IsAny<MyAsyncCompletedEventHandler>())).Callback<string, MyAsyncCompletedEventHandler>(
(s, c) =>
{
c = (sender, args) =>
args.Result = new List<Vehicle>
{
new Vehicle {Name = "TR3B"},
new Vehicle {Name = "Aurora"},
new Vehicle {Name = "HAUC"}
}.ToArray();
});
var testee = new VehiclesViewModel(vehiclesMock.Object);
Assert.AreEqual(3,testee.VehicleRows.Count);
}
}
但是测试失败了。如何模拟回调以正确测试 ViewModel?
我有一个带有示例的 github 存储库:https ://github.com/tbremeyer/TestEventHandler.git
解决方案
在您的示例测试中,当您应该调用传递给模拟回调的委托时,您试图在模拟回调中定义委托。
查看您提供的测试的以下重构,该重构捕获回调、调用它并验证预期行为
[Test]
public void AllVehiclesFromCallBackEndUpInProperty() {
//Arrange
MyAsyncCompletedEventHandler handler = null;
var vehiclesMock = new Mock<IVehicles>();
vehiclesMock
.Setup(_ => _.ListVehicles(It.IsAny<string>(), It.IsAny<MyAsyncCompletedEventHandler>()))
.Callback<string, MyAsyncCompletedEventHandler>((secret, callback) => {
//capture the delegate for later use;
handler = callback;
});
var subjectUnderTest = new VehiclesViewModel(vehiclesMock.Object);
//check to make sure the hanler as been set at this point
Assert.IsNotNull(handler);
var vehicles = new List<Vehicle> {
new Vehicle {Name = "TR3B"},
new Vehicle {Name = "Aurora"},
new Vehicle {Name = "HAUC"}
}.ToArray();
int expected = vehicles.Length;
var eventArgs = new MyAsyncCompletedEventArgs(null) {
Result = vehicles
};
//Act (invoke the delegate)
handler.Invoke(vehiclesMock.Object, eventArgs);
//Assert
int actual = subjectUnderTest.VehicleRows.Count;
Assert.AreEqual(expected, actual);
}
该测试更好地代表了被测对象的实际行为。
推荐阅读
- javascript - Vue.JS Canvas 绘图 iPad 兼容性
- ios - 无法从写入事务中注册通知块
- apache - Apache localhost 仅在 Ubuntu 18.04 上?
- hyperledger-fabric - 在哪里放置用户证书 hyperledger Fabric
- c++ - WaitForSingleObject 不等待进程结束
- javascript - Jquery datatable 能够展开/折叠除之前已经展开/折叠的单个行之外的所有行
- javascript - JavaScript 类和“this”
- python - 通过 Youtube api 搜索后如何获取 Youtube 视频
- css - 悬停在小尺寸视图中充当点击
- python - 从文本文件 Python 中提取 URL 和 TITLE