如何使用 SelectMany 测试 ReactiveUI 调用异步方法

问题描述 投票:0回答:1

我正在尝试为在我的模型(Foo)上调用异步方法的 Viewmodel 编写集成测试。 但是我无法让定时/线程/异步处理工作。

我已经将问题简化为下面的代码。目前此测试失败,因为 myFoo.Value 的实际值为 0 而不是 123。

using System.Reactive;
using Microsoft.Reactive.Testing;
using ReactiveUI.Testing;
using ReactiveUI.Fody.Helpers;
using ReactiveUI;
using System.Reactive.Linq;
using System.Reactive.Concurrency;

namespace Cooler.Test;

public class Foo
{
    public int Value { get; private set; }

    public Foo() => Value = 42;

    public async Task<Unit> SetValueAsync(int value)
    {
        await RxApp.TaskpoolScheduler.Sleep(TimeSpan.FromMilliseconds(10));
        Value = value;
        return Unit.Default;
    }
}

public class ViewModel : ReactiveObject
{
    public ViewModel(Foo foo)
    {
        this.WhenAnyValue(x => x.Setpoint)
            //.Skip(1) // Skip the initial value
            .ObserveOn(RxApp.MainThreadScheduler)
            .SelectMany(foo.SetValueAsync)
            .Subscribe();
    }

    [Reactive]
    public int Setpoint { get; set; }
}


public class Test
{
    [Fact]
    public void ShouldCallAsyncMethodOnSettingReactiveSetpoint()
    {
        new TestScheduler().With(scheduler =>
        {
            //set
            var myFoo = new Foo();
            var myVm = new ViewModel(myFoo);

            //act
            scheduler.AdvanceBy(1); //process the initial value if not skipped
            scheduler.AdvanceByMs(20); //async processing

            myVm.Setpoint = 123;
            scheduler.AdvanceBy(2); //process reactive
            scheduler.AdvanceByMs(20); //I expect it to process setpoint setting

            //assert
            Assert.Equal(123, myFoo.Value);
        });
    }
}

我预计该值为 123。但是 foo.SetValueAsync 未使用 123 进行调用。仅使用值 0 进行初始调用。如果我使用 Skip(1) 行,则该值为 42,从之前的结果来看,这是合乎逻辑的。

为什么这个测试失败?

c# unit-testing asynchronous reactiveui
1个回答
0
投票

我错误地认为 SelectMany 调用的方法也可以在 RxApp.MainThreadScheduler 上运行。事实并非如此。因此,在调用 SetValueAsync 之前,Assert 已完成。

© www.soinside.com 2019 - 2024. All rights reserved.