具有时间延迟的C#单元测试通过调试但在构建服务器上失败

时间:2017-07-14 06:45:49

标签: c# unit-testing timer

我在ASP.NET核心中有一个类,它使用Threading.Timer在给定的时间间隔内运行一个小任务(因为在Core中没有Timer.Timer)。现在我编写了一个单元测试,用于检查作业运行的时间:

[Fact]
    public async void IntervalExecutionTest()
    {
        var target = new PeriodicaBackgroundJobRunner();
        var testJob = new PeriodicalJobForTest();

        target.Start(1/*run every second*/, testJob);

        await Task.Delay(2500).ContinueWith(c =>
        {
            Assert.Equal(3, testJob.ExecutedCounter);
        });
    }

测试工作如下:

 private class PeriodicalJobForTest : IPeriodicalJob
    {
        public int ExecutedCounter { get; private set; }

        public void Execute(object state)
        {
            this.ExecutedCounter++;
        }
    }

因此,等待时间为2.5秒,我预计它会在0,1和2上运行3次。

在调试测试过程中。然而,构建服务器失败并说“预期3,实际1”。

为什么?有什么不同?一旦它实际部署到Azure,我是否也会在生产中遇到问题?

注意:我也尝试过使用Thread.Sleep(),结果相同。

如果问题实际上可能与测试实现中的类有关,那么该类看起来像这样:

public class PeriodicaBackgroundJobRunner : IPeriodicaBackgroundJobRunner
{
    private Threading.Timer timer;

    public void Start(int interval, IPeriodicalJob job)
    {
        interval = Math.Max(interval, 1) * 1000;

        if (this.timer == null)
        {
            this.timer = new Timer(new TimerCallback(job.Execute), null, Timeout.Infinite, interval);
        }

        this.timer.Change(0, interval);
    }

    public void Stop()
    {
        if (this.timer != null)
        {
            this.timer.Change(Timeout.Infinite, Timeout.Infinite);
        }
    }
}

1 个答案:

答案 0 :(得分:0)

嗯,不确定问题究竟是什么,但它与Threading.Timer有关。当我在没有计时器的情况下重写课程时,测试工作正常:

public class PeriodicaBackgroundJobRunner : IPeriodicaBackgroundJobRunner
{
    private CancellationTokenSource cancellationToken;

    public void Start(int interval, IPeriodicalJob job)
    {
        Task.Run(async () =>
        {
            interval = Math.Max(interval, 1) * 1000;

            this.cancellationToken = new CancellationTokenSource();

            while (true)
            {
                job.Execute(null);
                await Task.Delay(interval, this.cancellationToken.Token);
            }
        });
    }

    public void Stop()
    {
        if (this.cancellationToken != null)
        {
            this.cancellationToken.Cancel();
        }
    }
}