Tôi đang viết kiểm tra đơn vị và nhận ngoại lệ khi cố gắng tăng sự kiện từ mô hình lớp trừu tượng. Đây là đoạn mã mẫu:C# và Moq, tăng sự kiện được khai báo trong giao diện từ mô hình lớp trừu tượng
public abstract class AbstractBase : EntityObject
{}
[TestMethod]
public void MyTest()
{
var mock = new Mock<AbstractBase>();
var notificationMock = entityMock.As<INotifyPropertyChanged>();
var propertyChangedMapper = new PropertyChangedMapper();
bool eventReceived = false;
propertyChangedMapper.MyPropertyChanged +=
(sender, eventArgs) =>
{
eventReceived = true;
};
propertyChangedMapper.Subscribe((AbstractBase)notificationMock.Object);
Assert.IsFalse(eventReceived);
notificationMock.Raise(e=>e.PropertyChanged += null,
new PropertyChangedEventArgs("Property1"));
Assert.IsTrue(eventReceived);
}
Rõ ràng là tôi có thể sử dụng mô hình trên INotifyPropertyChanged
và sự kiện được tăng tốt, nhưng bên trong PropertyChangedMapper
tôi cần phải đúc người gửi để AbstractBase
mà thất bại nếu sử dụng Mock<INotifyPropertyChanged>
EDIT: Theo đề xuất sử dụng Mock.As<>()
có vẻ là cách đúng đắn, vấn đề duy nhất ở trên là sự kiện tăng từ notificationMock
không liên quan gì đến bản gốc của đối tượng. Mã số:
notificationMock.Object.PropertyChanged += (s, e) =>
{
var result = "this one is fired as it should";
};
mock.Object.PropertyChanged += (s, e) =>
{
var result = "this one is not called but is actually what I need";
};
notificationMock.Raise(e => e.PropertyChanged += null,
new PropertyChangedEventArgs("Property1"));
Không cần biết người nào gọi, miễn là người nào gọi. Đoán của tôi là bạn có thể thực sự thiết lập một trong hai hoặc khác. Nhưng thiết lập cả hai sẽ dẫn đến giả trong nội bộ lựa chọn một trong khác. –
Để có thêm bằng chứng cho thấy nó không quan trọng được gọi, hãy xem xét rằng hệ thống kiểu hoạt động tương tự cho các thành viên ảo và phần ghi đè của chúng. Ví dụ, nếu bạn thêm vào AbstractBase một ghi đè cho sự kiện INPC của EntityObject, không có cách nào cho bất kỳ mã nào dùng AbstractBase để buộc phiên bản của EntityObject được gọi. Ngay cả khi bạn truyền vào EntityObject, thành viên AbstractBase sẽ được gọi. Khi một thành viên cơ sở bị ghi đè, chỉ có lớp bắt nguồn mới có thể truy cập thành viên cơ sở ban đầu. –