gpt4 book ai didi

c# - 使用 FromAsyncPattern 进行单元测试

转载 作者:行者123 更新时间:2023-11-30 19:33:45 25 4
gpt4 key购买 nike

Reactive Extensions 有一个性感的小钩子(Hook)来简化调用异步方法:

var func = Observable.FromAsyncPattern<InType, OutType>(
myWcfService.BeginDoStuff,
myWcfService.EndDoStuff);

func(inData).ObserveOnDispatcher().Subscribe(x => Foo(x));

我在 WPF 项目中使用它,它在运行时运行良好。

不幸的是,在尝试对使用此技术的方法进行单元测试时,我遇到了随机失败。包含此代码的测试每五次执行中就有 3 次失败。

这是一个示例测试(使用 Rhino/unity 自动模拟容器实现):

[TestMethod()]
public void SomeTest()
{
// arrange
var container = GetAutoMockingContainer();

container.Resolve<IMyWcfServiceClient>()
.Expect(x => x.BeginDoStuff(null, null, null))
.IgnoreArguments()
.Do(
new Func<Specification, AsyncCallback, object, IAsyncResult>((inData, asyncCallback, state) =>
{
return new CompletedAsyncResult(asyncCallback, state);
}));

container.Resolve<IRepositoryServiceClient>()
.Expect(x => x.EndDoStuff(null))
.IgnoreArguments()
.Do(
new Func<IAsyncResult, OutData>((ar) =>
{
return someMockData;
}));

// act
var target = CreateTestSubject(container);

target.DoMethodThatInvokesService();

// Run the dispatcher for everything over background priority
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Background, new Action(() => { }));

// assert
Assert.IsTrue(my operation ran as expected);
}

我看到的问题是我指定在异步操作完成时运行的代码(在本例中为 Foo(x))从未被调用。我可以通过在 Foo 中设置断点并观察它们永远不会到达来验证这一点。此外,我可以在调用 DoMethodThatInvokesService(启动异步调用)后强制延迟很长时间,并且代码仍然不会运行。我确实知道调用 Rx 框架的代码行被调用了。

我尝试过的其他事情:

这将我的失败率提高到大约五分之一,但它们仍然会发生。

  • 我重写了 Rx 代码以使用简单的 jane 异步模式。这行得通,但是我的开发者 self 真的很喜欢使用 Rx 而不是无聊的旧的开始/结束。

最后我确实有一个解决办法(即不使用 Rx),但我觉得它并不理想。如果过去有人遇到过这个问题并找到了解决方案,我非常乐意听到。

更新:

我也是posted on the Rx forums ,他们将在即将发布的版本中包含一个测试调度程序。一旦可用,这可能是最终的解决方案。

最佳答案

问题是 MSTest.exe 运行一个 Dispatcher(即 Dispatcher.Current != null),所以 ObserveOnDispatcher 可以工作。但是,这个 Dispatcher 什么都不做! (即排队的调度程序项目将被忽略)您编写的任何明确使用 Schedule.Dispatcher 的代码都是不可测试的

我在 ReactiveUI 中通过暴力解决了这个问题- 这是重要的部分:

https://github.com/reactiveui/ReactiveUI/blob/master/ReactiveUI/RxApp.cs#L99

我们基本上设置了一个定义默认调度程序的全局变量,然后我们尝试检测我们何时进入测试运行器。

然后,在我们实现 IObservable 的类中,所有类都采用一个 IScheduler 参数,其默认值最终将成为全局默认调度程序。我本可以做得更好,但这对我有用,并使 ViewModel 代码再次可测试。

关于c# - 使用 FromAsyncPattern 进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3017804/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com