使用 Caliburn 事件聚合器为包装 PublishOnUIThreadAsync 的方法设置最小起订量
Setup moq with Caliburn event aggregator for a method wrapping PublishOnUIThreadAsync
从我的 中,我了解到我必须执行 Mock.Setup
才能让 eventAggregatorMoq
了解 return 数据。
public void Navigate() {
eventAggregator.PublishOnUIThreadAsync(new MyEvent(5));
}
下面的方法很好地覆盖了上面的包装器方法,它不是 await
ing 和 returning void
.
eventAggregatorMock.Verify(_ => _.Publish(It.IsAny<MyEvent>(),
It.IsAny<Action<System.Action>>()), Times.Once);
那么,如果我正在等待 returns 任务的方法,我该如何设置。
public async Task Navigate() {
await eventAggregator.PublishOnUIThreadAsync(new MyEvent(5));
}
基于PublishOnUIThreadAsync
扩展方法,其中returns一个Task
/// <summary>
/// Publishes a message on the UI thread asynchrone.
/// </summary>
/// <param name="eventAggregator">The event aggregator.</param>
/// <param name="message">The message instance.</param>
public static Task PublishOnUIThreadAsync(this IEventAggregator eventAggregator, object message) {
Task task = null;
eventAggregator.Publish(message, action => task = action.OnUIThreadAsync());
return task;
}
您会注意到任务是在 Publish
执行的操作中分配的。您需要调用操作,以便通过确保调用 delegate/action 来分配任务。您可以在模拟方法的回调中执行此操作。
以下最小示例演示了如何执行此操作。请注意 Publish
是如何设置回调以调用传入的 Action 参数的。
[TestClass]
public class MyTestClass {
[TestMethod]
public async Task _EventAggregator_Should_Publish_OnUIThread() {
//Arrange
MyEvent navigateEvent = null;
var eventAggregatorMock = new Mock<IEventAggregator>();
eventAggregatorMock
.Setup(x => x.Publish(It.IsAny<MyEvent>(), It.IsAny<Action<System.Action>>()))
.Callback((object message, Action<System.Action> marshal) => {
navigateEvent = (MyEvent)message;
marshal(() => { });//Invoking action that would cause task to be assigned
});
var sut = new MyClass(eventAggregatorMock.Object);
//Act
await sut.Navigate();
//Assert
navigateEvent.Should().NotBeNull();
eventAggregatorMock.Verify(_ => _.Publish(It.IsAny<MyEvent>(),
It.IsAny<Action<System.Action>>()), Times.Once);
}
public class MyEvent {
private int p;
public MyEvent(int p) {
// TODO: Complete member initialization
this.p = p;
}
}
public class MyClass {
IEventAggregator eventAggregator;
public MyClass(IEventAggregator eventAggregator) {
this.eventAggregator = eventAggregator;
}
public async Task Navigate() {
await eventAggregator.PublishOnUIThreadAsync(new MyEvent(5));
}
}
}
从我的 Mock.Setup
才能让 eventAggregatorMoq
了解 return 数据。
public void Navigate() {
eventAggregator.PublishOnUIThreadAsync(new MyEvent(5));
}
下面的方法很好地覆盖了上面的包装器方法,它不是 await
ing 和 returning void
.
eventAggregatorMock.Verify(_ => _.Publish(It.IsAny<MyEvent>(),
It.IsAny<Action<System.Action>>()), Times.Once);
那么,如果我正在等待 returns 任务的方法,我该如何设置。
public async Task Navigate() {
await eventAggregator.PublishOnUIThreadAsync(new MyEvent(5));
}
基于PublishOnUIThreadAsync
扩展方法,其中returns一个Task
/// <summary>
/// Publishes a message on the UI thread asynchrone.
/// </summary>
/// <param name="eventAggregator">The event aggregator.</param>
/// <param name="message">The message instance.</param>
public static Task PublishOnUIThreadAsync(this IEventAggregator eventAggregator, object message) {
Task task = null;
eventAggregator.Publish(message, action => task = action.OnUIThreadAsync());
return task;
}
您会注意到任务是在 Publish
执行的操作中分配的。您需要调用操作,以便通过确保调用 delegate/action 来分配任务。您可以在模拟方法的回调中执行此操作。
以下最小示例演示了如何执行此操作。请注意 Publish
是如何设置回调以调用传入的 Action 参数的。
[TestClass]
public class MyTestClass {
[TestMethod]
public async Task _EventAggregator_Should_Publish_OnUIThread() {
//Arrange
MyEvent navigateEvent = null;
var eventAggregatorMock = new Mock<IEventAggregator>();
eventAggregatorMock
.Setup(x => x.Publish(It.IsAny<MyEvent>(), It.IsAny<Action<System.Action>>()))
.Callback((object message, Action<System.Action> marshal) => {
navigateEvent = (MyEvent)message;
marshal(() => { });//Invoking action that would cause task to be assigned
});
var sut = new MyClass(eventAggregatorMock.Object);
//Act
await sut.Navigate();
//Assert
navigateEvent.Should().NotBeNull();
eventAggregatorMock.Verify(_ => _.Publish(It.IsAny<MyEvent>(),
It.IsAny<Action<System.Action>>()), Times.Once);
}
public class MyEvent {
private int p;
public MyEvent(int p) {
// TODO: Complete member initialization
this.p = p;
}
}
public class MyClass {
IEventAggregator eventAggregator;
public MyClass(IEventAggregator eventAggregator) {
this.eventAggregator = eventAggregator;
}
public async Task Navigate() {
await eventAggregator.PublishOnUIThreadAsync(new MyEvent(5));
}
}
}