1

私は以下のようなイベント調達方法を持っています:

public class Events {

    public event EventHandler<CustomEventArgs> Succeed;

    public virtual void OnSucceed(object sender, params object[] data)
    {
        CustomEventArgs args = new CustomEventArgs(data);

        EventHandler<CustomEventArgs> _succeed = Succeed;

        if (_succeed != null)
        {
            _succeed(sender, args);
        }

    }}

OnSucceedメソッドの単体テストを作成しました( FluentAssertionsを使用):

    [Test]
    public void SucceedShouldNotBeRaisedTest()
    {
        Events events = new Events();

        events.MonitorEvents();

        events.OnSucceed(this,"somedata");

        events.ShouldNotRaise("Succeed");
    }

イベントのサブスクライバーがないため、Succeed イベントが発生しないことを期待しています

しかし、Succeed イベントが発生すると、テストは失敗します。これの何が問題なの?!

4

1 に答える 1

1

を呼び出すとevents.MonitorEvents();FluentAssertionsは自動的に公開イベントをサブスクライブして、イベントが発生したことを検出します。

条件は常に次のように評価されるため、テストは失敗しtrueますif (_succeed != null)。テストするとき、イベントは常にとは異なりますnull

ここで、JonSkeetによって提案された次のアプローチをお勧めします。

public event EventHandler<CustomEventArgs> Succeed = delegate { } ;

上記のイベント宣言を使用すると、イベントが発生することはありませんnull(クラスの外部からイベントを割り当てることはできません)

注:次のように、イベントの背後にあるデリゲートをそのクラス内でnullに割り当てることができます。

this.Succeed = null;

上記のステートメントは、イベント自体ではなく、イベントの背後にあるデリゲートをnullに割り当てています。通常、このようなことをする必要はありませんが、そうする場合は、次のようにイベントを再初期化する必要があります。

this.Succeed = null;
this.Succeed = delegate { };

if(this.MyEvent != null)これらの提案に従うと、イベントがnullになることはなく、イベントを発生させるために条件を呼び出す必要がなくなります。(この状態は完全に技術的なものであり、ドメイン自体とは関係がないことに注意してください。)

その技術的条件を取り除いたので、実際にドメインルールに焦点を合わせて、いつイベントを発生させるかを決定できます。

最後のステップは、以下を削除するif (_succeed != null)ことです。現在のドメインに基づいてイベントを発生させる必要があるかどうかを示す条件を追加します。

if(shouldRaiseEvent)
{
    EventHandler<CustomEventArgs> _succeed = Succeed;

    _succeed(...);
}

テストでは、イベントを発生させる、または発生させないために、必要な条件でテスト対象を構成する必要があります。

完全なサンプル:

public class Events {

public event EventHandler<CustomEventArgs> Succeed = delegate { };

public virtual void OnSucceed(object sender, params object[] data)
{
    if (/*[optional] here your domain condition that will indicate if the event should be raised*/)
    {
        // this is a best practice to deal with multi-threading situations
        var _succeed = this.Succeed;
        var args = new CustomEventArgs(data);

        _succeed(sender, args);
    }

}
}
于 2012-10-01T08:28:53.327 に答える