2

タイマー クラスを作成していますが、テスト パスを作成できません。タイマーの時間が経過したときにメソッドが呼び出されることをテストしたいと思います。

私は次のクラスを持っています:

public class TimeOutTimer
{
    private readonly ISubscriber _subscriber;
    private Timer _timer;

    public TimeOutTimer(ISubscriber subscriber)
    {
        _subscriber = subscriber;
    }

    public void Start()
    {
        _timer = new Timer(1000);
        _timer.Start();
        _timer.Elapsed += TimerOnElapsed;
    }

    private void TimerOnElapsed(object sender, ElapsedEventArgs elapsedEventArgs)
    {
        _subscriber.TimeReached();   
    }
}

そして、Moq を使用したテスト:

[Test]
public void Start_WithValidParameters_TriggersTimeReached()
{
    var subscriberMock = new Mock<ISubscriber>();
    var timer = new TimeOutTimer(subscriberMock.Object);

    timer.Start();

    subscriberMock.Verify(subscriber => subscriber.TimeReached());
}

タイマーを取り出して _subscriber.TimeReached() を直接呼び出すと、機能します。

私は何か間違ったことをしていますか?

4

3 に答える 3

4

あなたの例では、イベントは 1000 ミリ秒後に呼び出されますが、すぐに確認できます。明らかに、その時点でイベントを呼び出すことはできません。

簡単な方法は、テストでスレッドをスリープ状態にすることです。

[Test]
public void Start_WithValidParameters_TriggersTimeReached()
{
    var subscriberMock = new Mock<ISubscriber>();
    var timer = new TimeOutTimer(subscriberMock.Object);        

    timer.Start();
    Thread.Sleep(1000);

    subscriberMock.Verify(subscriber => subscriber.TimeReached());
}

ただし、これは時間ベースのクラスの単体テストを生成する正しい方法ではありません。

正しい方法は、ITimerインターフェースを作成し、それを に基づくアダプターによって実装することTimerです。

その後、ITimerは の依存関係になりTimeoutTimer、コンストラクターまたはプロパティとして渡されます。

次に、テストでタイマーをモックして、待機せずにテストと同期できるようにします (たとえば、クラスを制御してイベントを手動でトリガーできるようにするなど)。

于 2012-10-05T20:24:45.710 に答える
2

さて、ここでは非同期操作を扱っています。ハンドラーにブレークポイントを設定してコードをデバッグし、検証行でスペルを待機すると、検証行をステップオーバーすると、ハンドラーが実行されることがわかります。問題は、ハンドラーが起動する前にテストが終了することです。

于 2012-10-05T20:24:32.463 に答える
-1

テストで Elapsed イベントを発生させる必要があります。

問題を引き起こしているのは新しいタイマーだと思います。注入可能にしてから、テストに注入してイベントを発生させることができます。

于 2012-10-05T20:25:38.733 に答える