使用 Rhino Mocks 进行单元测试 INotifyPropertyChanged
Unit Test INotifyPropertyChanged using Rhino Mocks
我有一个 class 实现了 INotifyPropertyChanged,我需要测试这个接口是否实现正确。我想使用 Rhino Mock 对象来执行此操作。
class MyClass : INotifyPropertyChanged
{
public int X
{
get => ...;
set => ... // should check if value changes and raise event PropertyChanged
}
}
我想测试的是,当 X 更改值时,该事件 PropertyChanged 仅使用正确的参数调用一次。
MyClass testObject = new MyClass();
// the mock:
PropertyChangedEventHandler a = MockRepository.GenerateMock<PropertyChangedEventHandler>();
testObject.PropertyChanged += a;
// expect that the mock will be called exactly once, with the proper parameters
a.Expect( (x) => ???)
.Repeat()
.Once();
// change X, and verify that the event handler has been called exactly once
testObject.X = testObject.X + 1;
a.VerifyAllExpectations(); ???
我认为我在正确的道路上,但我无法让它发挥作用。
有时候,如果使用真实的东西没有连锁反应,真的没有必要使用模拟。
以下简单示例创建委托实例并验证预期行为
What I want to test, is that when X changes value, that event PropertyChanged is called exactly once, with the proper parameters.
[TestClass]
public class MyClassTests {
[TestMethod]
public void Should_Call_PropertyChanged_Once() {
//Arrange
//Store calls
IDictionary<string, int> properties = new Dictionary<string, int>();
PropertyChangedEventHandler handler = new PropertyChangedEventHandler((s, e) => {
if (!properties.ContainsKey(e.PropertyName))
properties.Add(e.PropertyName, 0);
properties[e.PropertyName]++;
});
MyClass testObject = new MyClass();
testObject.PropertyChanged += handler;
string expectedPropertyName = nameof(MyClass.X);
int expectedCount = 1;
//Act
testObject.X = testObject.X + 1;
//Assert - using FluentAssertions
properties.Should().ContainKey(expectedPropertyName);
properties[expectedPropertyName].Should().Be(expectedCount);
}
class MyClass : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged = delegate { };
void raisePropertyChanged([CallerMemberName]string propertyName = null) {
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
int x;
public int X {
get => x;
set {
if (value != x) {
x = value;
raisePropertyChanged();
}
}
}
}
}
我有一个 class 实现了 INotifyPropertyChanged,我需要测试这个接口是否实现正确。我想使用 Rhino Mock 对象来执行此操作。
class MyClass : INotifyPropertyChanged
{
public int X
{
get => ...;
set => ... // should check if value changes and raise event PropertyChanged
}
}
我想测试的是,当 X 更改值时,该事件 PropertyChanged 仅使用正确的参数调用一次。
MyClass testObject = new MyClass();
// the mock:
PropertyChangedEventHandler a = MockRepository.GenerateMock<PropertyChangedEventHandler>();
testObject.PropertyChanged += a;
// expect that the mock will be called exactly once, with the proper parameters
a.Expect( (x) => ???)
.Repeat()
.Once();
// change X, and verify that the event handler has been called exactly once
testObject.X = testObject.X + 1;
a.VerifyAllExpectations(); ???
我认为我在正确的道路上,但我无法让它发挥作用。
有时候,如果使用真实的东西没有连锁反应,真的没有必要使用模拟。
以下简单示例创建委托实例并验证预期行为
What I want to test, is that when X changes value, that event PropertyChanged is called exactly once, with the proper parameters.
[TestClass]
public class MyClassTests {
[TestMethod]
public void Should_Call_PropertyChanged_Once() {
//Arrange
//Store calls
IDictionary<string, int> properties = new Dictionary<string, int>();
PropertyChangedEventHandler handler = new PropertyChangedEventHandler((s, e) => {
if (!properties.ContainsKey(e.PropertyName))
properties.Add(e.PropertyName, 0);
properties[e.PropertyName]++;
});
MyClass testObject = new MyClass();
testObject.PropertyChanged += handler;
string expectedPropertyName = nameof(MyClass.X);
int expectedCount = 1;
//Act
testObject.X = testObject.X + 1;
//Assert - using FluentAssertions
properties.Should().ContainKey(expectedPropertyName);
properties[expectedPropertyName].Should().Be(expectedCount);
}
class MyClass : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged = delegate { };
void raisePropertyChanged([CallerMemberName]string propertyName = null) {
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
int x;
public int X {
get => x;
set {
if (value != x) {
x = value;
raisePropertyChanged();
}
}
}
}
}