使用Tasks完成单元测试

时间:2016-03-23 15:56:47

标签: c# unit-testing

我有一个永远在运行的单元测试:

<script src="https://maps.googleapis.com/maps/api/js"></script>
<div id="map_canvas"></div>

manager.Send()方法是:

[Test]
public bool test()
{
    manager.Send(10);

    Thread.Sleep(1000);

    manager.Messages.Should().HaveCount(10);

    return true;
}

和SendEntity()方法:

private void Send()
{
    try
    {
        var entities = GetAllEntities();

        foreach (var group in entities.GroupBy(r => r.Priority))
        {
            var tasks = group.Select(entity => Task.Factory.StartNew(() => manager.SendEntity(entity))).ToList();
            Task.WaitAll(tasks.ToArray());

            if (tasks.All(r => r.Result.Result == true))
            {
                // some code here...
            }
        }
    }
    catch (Exception e)
    {
        logger.FatalException(e.Message, e);
    }
    finally
    {
        logger.Info("End...");
    }
}
单元测试管理器中的

。发送(10)永远运行。我对代码进行了调试,我发现问题出现在

public Task<bool> SendEntity(DeferredEntity entity)
{
    var taskCompletionSource = new TaskCompletionSource<bool>();

    try
    {
        logger.Info("Sending entity {0} with params: {1}", entity.Entity, GetEntityParams(entity));

        server.SendToServer(entity, (response, result) =>
        {
            taskCompletionSource.SetResult(result);
        });
    }
    catch (Exception e)
    {
        logger.FatalException(e.Message, e);
    }

    return taskCompletionSource.Task;
}

调试器在此行停止并永远休眠。我做错了什么?我将单元测试方法的返回值添加到bool(异步方法不会在void方法中抛出异常)。但它没有帮助。你有什么建议吗?

1 个答案:

答案 0 :(得分:2)

你在那里陷入僵局。 首先,你不必用

开始新的线程
Task.Factory.StartNew(() => manager.SendEntity(entity)

似乎SendToServer已经异步。

使用Task.Wait***/Task.Result也是一种不好的做法,使用异步流

private async Task Send()
{
    try
    {
        var entities = GetAllEntities();

        foreach (var group in entities.GroupBy(r => r.Priority))
        {
            var tasks = group
                .Select(entity => manager.SendEntity(entity))
                .ToArray();

            var results = await Task.WhenAll(tasks);
            if (results.All(result => result))
            {
                // some code here...
            }
        }
    }
    catch (Exception e)
    {
        logger.FatalException(e.Message, e);
    }
    finally
    {
        logger.Info("End...");
    }
}

但如果您不想重写发送方法,可以使用.ConfigureAwait(false)

return taskCompletionSource.Task.ConfigureAwait(false);

但无论如何,请删除StartNew - 您不需要这个。