MSTEST - асинхронный тест

Просто интересно, если кто-нибудь подумает так:

Это неправильный дизайн, чтобы иметь асинхронный вызов в TestInitialize, поскольку TestInitialize должен произойти до любого TestMethod.

Может ли это быть правильный подход, чтобы иметь асинхронный TestInitialize?

    private int val = 0;

    [TestInitialize]
    public async Task  TestMehod1()
    {
        var result = await LongRunningMethod();
        val = 10;
    }

    [TestMethod]
    public void  TestMehod2()
    {
        Assert.AreEqual(10, val);
    }

любая мысль?

Ответ 1

Вероятно, самый чистый способ сделать это состоит в том, чтобы TestInitialize запускал асинхронную операцию:

[TestClass]
public class UnitTestAsync
{
    private Task<int> val = null;

    [TestInitialize]
    public void TestInitializeMethod()
    {
        val = TestInitializeMethodAsync();
    }

    private async Task<int> TestInitializeMethodAsync()
    {
        return await LongRunningMethod();
    }

    private async Task<int> LongRunningMethod()
    {
        await Task.Delay(20);
        return 10;
    }

    [TestMethod]
    public async Task TestMehod2()
    {
        Assert.AreEqual(10, await val);
    }
}

Ответ 2

То, что вы хотите сделать, - использовать .Result или .Wait() для синхронного блокирования метода TestInitialize. Вы можете сделать следующее:

private int val = 0;

[TestInitialize]
public void TestMehod1()
{
    Task<object> result = await LongRunningMethod();
    result.Wait();

    val = 10;
}

[TestMethod]
public void  TestMehod2()
{
    Assert.AreEqual(10, val);
}

Ответ 3

Просто создайте массив задач для различных вызовов инициализации (каждая возвращаемая задача), а затем используйте Task.WaitAll()

    [ClassInitialize()]
    public static void Initialize(TestContext context)
    {
        List<Task> tasks = new List<Task>();
        tasks.Add(InitializeMethod1());
        tasks.Add(InitializeMethod2());
        Task.WaitAll(tasks.ToArray());
    }

    public static async Task InitializeMethod1()
    {
    }

    public static async Task InitializeMethod2()
    {
    }

Ответ 4

Ваш код правильный!

Чтобы уточнить этот ответ 5 лет, через 2 месяца после первоначального вопроса. В то время наличие async [TestInitialize] могло быть ошибкой компиляции, но в наши дни это не так.

Можно использовать async [TestInitialize], async [ClassInitialize] и async [TestMethod], просто используя await.

Использование async и await должным образом, вероятно, самый чистый способ сделать это. У меня есть что-то вроде следующего в моем коде, где мне нужно получить нашу структуру категорий, чтобы иметь возможность проверить, хорошо ли мои классы работают с имеющейся у нас структурой категорий.

private Category rootCategory;

[TestInitialize]
public async Task TestInitialize()
{
    var loader = new CategoryLoader();
    rootCategory = await loader.GetAllCategoriesAsync();
}

[TestInitialize] запускается перед каждым [TestMethod], поэтому в зависимости от того, что я пытаюсь здесь протестировать, может быть лучше загрузить только один раз, а затем сделать все утверждения, чтобы не платить за время загрузки несколько раз. Но вы должны быть осторожны, чтобы тесты не влияли друг на друга, чтобы получить согласованные и правильные результаты.

Просто обратите внимание, что это больше не модульное тестирование, так как я тестирую интеграцию с внешним сервисом.