c# 中的异步单元测试设置

Async UnitTests setup in c#

我的每个单元测试都需要一个登录用户,这迫使我在测试中进行异步调用(登录)SetUp

我找不到使这项工作正常进行的方法,我要么遇到空指针异常,要么遇到无效的设置签名。

public async void SetUp() {}

这可能是因为我没有登录,所以我对我的对象的所有测试都失败了。

public async Task SetUp() {}

忽略我的所有测试,因为设置的签名无效。

而且我不想在每次测试中都复制我的 X 行设置,因为它们完全相同并且...这就是设置的目的。

我错过了什么?这看起来像是一个微不足道的问题。

这是我现在的,为了展示一些东西

CreateTicketViewModel _viewModel;

        [SetUp()]
        public async void SetUp()    //I have tried using Task instead of void
        {

            IUserService userService = Dependency.Instance.Resolve<IUserService>();
            await userService.LoginAsync(this.UserName, this.Password);

            _viewModel = Dependency.Instance.Resolve<CreateTicketViewModel>();
        }

        [TearDown()]
        public void TearDown()
        {
            _viewModel = null;  // I have tried removing this
        }

        [Test()]
        public void Initialization()
        {
            // If I put what's in SetUp here and add "async" before void,
            // it works just fine

            Assert.IsNotNull(_viewModel);
            Assert.IsNotNull(_viewModel.Ticket);
        }

你能不能让你的 SetUp 方法完全不异步然后写这个?

new Task(() => userService.LoginAsync(this.UserName, this.Password)).RunSynchronously()

根据您使用的单元测试框架,async框架可能无法正确处理设置。

在 NUnits 案例中,我认为它还不支持异步设置方法。

所以您应该在设置中做的是同步等待登录完成:

userService.LoginAsync(this.UserName, this.Password).Wait();

编辑: 看起来这是一个悬而未决的问题 https://github.com/nunit/nunit/issues/60

MSTest 也是如此。

不支持异步设置,但支持异步测试方法。你可以让你的测试方法异步而不是设置方法。

[TestFixture]
public class AsyncSetupTest
{
    private Task<CreateTicketViewModel> viewModelTask;

    [SetUp()]
    public void SetUp()
    {
        viewModelTask = Task.Run(async () =>
        {
            IUserService userService = Dependency.Instance.Resolve<IUserService>();
            await userService.LoginAsync(this.UserName, this.Password);

            return Dependency.Instance.Resolve<CreateTicketViewModel>();
        });
    }

    [Test()]
    public async Task Initialization()
    {
        CreateTicketViewModel viewModel = await viewModelTask;

        Assert.IsNotNull(viewModel);
        Assert.IsNotNull(viewModel.Ticket);
    }
}

想法是,我们不是在 Setup 方法中完成所有设置工作,而是创建一个 Task 表示设置完成并在 Test 方法中等待它。

这样您就不会重复所有设置逻辑。但是只是从所有测试方法中的 Task 中提取 ViewModel。