6

Moq バージョン: 3.1.416.3

イベントがサブスクライブ解除されていないことが原因のバグが見つかりました。イベントがサブスクライブされていないことを確認する単体テストを作成しようとしています。を使用してこれを確認することは可能Mock<T>.Verify(expression)ですか?

私の最初の考えは:

mockSource.Verify(s => s.DataChanged -= It.IsAny<DataChangedHandler>());

しかしどうやら

式ツリーに代入演算子を含めることはできません

それから私は試しました

mockSource.VerifySet(s => s.DataChanged -= It.IsAny<DataChangedHandler>());

しかし、それは私に与えます

System.ArgumentException: 式はプロパティ セッターの呼び出しではありません。

登録解除が行われたことをどのように確認できますか?

イベントの利用方法

public class Foo
{
    private ISource _source;

    public Foo(ISource source)
    {
        _source = source;
    }

    public void DoCalculation()
    {
        _source.DataChanged += ProcessData;

        var done = false;

        while(!done)
        {
            if(/*something is wrong*/)
            {
                Abort();
                return;
            }
            //all the things that happen
            if(/*condition is met*/)
            {
                done = true;
            }
        }

        _source.DataChanged -= ProcessData;
    }

    public void Abort()
    {
        _source.DataChanged -= ProcessData; //this line was added to fix the bug
         //other cleanup
    }

    private void ProcessData(ISource)
    {
        //process the data
    }
}

コードの複雑な性質を無視して、外部ハードウェアからの信号を扱っています。これは実際にはアルゴリズムにとって理にかなっています。

4

2 に答える 2

1

ターゲット クラス外のイベントから invocationList を取得する汚い方法がありますが、これはイベントの目的に反するため、テストまたはデバッグの目的でのみ使用する必要があります。

これは、イベントが顧客の実装 (追加/削除) で実装されていない場合にのみ機能します。イベントにイベント アクセサーがある場合、eventInfo2FieldInfo は null を返します。

 Func<EventInfo, FieldInfo> eventInfo2FieldInfo = eventInfo => mockSource.GetType().GetField(eventInfo.Name, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField);
 IEnumerable<MulticastDelegate> invocationLists = mockSource.GetType().GetEvents().Select(selector => eventInfo2FieldInfo(selector).GetValue(mockSource)).OfType<MulticastDelegate>();

これで、ターゲット クラスのすべてのイベントの呼び出しリストが取得され、特別なイベントのサブスクライブが解除されたかどうかをアサートできるはずです。

于 2013-09-26T09:18:42.797 に答える