2

特定のCancellationTokenSourceがメソッド呼び出しの実際のパラメーターとして使用されていることを確認しようとしています。

        public void DataVerification(Object sender, EventArgs e)
        {
            _entity.PopulateEntityDataVerificationStage(_view.DataTypeInputs, _view.ColumnNameInputs, _view.InitialRow, _view.FinalRow, _view.CurrencyPair, _view.CsvFilePath, _view.ErrorLogFilePath);

            //...

            CancellationTokenSource tempCsvFileVerificationCancellation = new CancellationTokenSource();

            _source.Source = tempCsvFileVerificationCancellation;

           //Want to verify that TempCsvFileVerificationCancellation.Token is passed into the following method.
            _verify.SetupCsvFileVerification(_entity, tempCsvFileVerificationCancellation.Token);

           //...
        } 

以下は私のテストです:

    [Test]
    public void DataVerification_SetupCsvFileVerification_CorrectInputs()
    {
        Mock<IMainForm> view = new Mock<IMainForm>();

        Mock<IUserInputEntity> entity = new Mock<IUserInputEntity>();

        Mock<ICsvFileVerification> verify = new Mock<ICsvFileVerification>();
        verify.Setup(x => x.SetupCsvFileVerification(It.IsAny<UserInputEntity>(), It.IsAny<CancellationToken>()));

        CancellationTokenSource cts = new CancellationTokenSource();

        Mock<ICancellationTokenSource> source = new Mock<ICancellationTokenSource>();
        source.SetupSet(x => x.Source = It.IsAny<CancellationTokenSource>()).Callback<CancellationTokenSource>(value => cts = value);
        source.SetupGet(x => x.Source).Returns(cts);
        source.SetupGet(x => x.Token).Returns(cts.Token);

        MainPresenter presenter = new MainPresenter(view.Object, entity.Object, verify.Object, source.Object);

        presenter.DataVerification(new object(), new EventArgs());

        verify.Verify(x => x.SetupCsvFileVerification(entity.Object, source.Object.Token));
    }

エラーメッセージは次のとおりです。

少なくとも1回はモックでの呼び出しが必要ですが、実行されませんでした。x => x.SetupCsvFileVerification(.entity.Object、(Object).source.Object.Token)セットアップが構成されていません。

sourceで表されるクラスは次のとおりです。

public interface ICancellationTokenSource
{
    void Cancel();

    CancellationTokenSource Source { get; set; }

    CancellationToken Token { get; }
}

public class CancellationTokenSourceWrapper : ICancellationTokenSource
{
    private CancellationTokenSource _source;

    public CancellationTokenSourceWrapper(CancellationTokenSource source)
    {
        _source = source;
    }

    public CancellationTokenSource Source
    {
        get
        {
            return _source;
        }
        set
        {
            _source = value;
        }
    }


    public CancellationToken Token 
    {
        get
        {
            return Source.Token;
        }
    }

    public void Cancel()
    {
        _source.Cancel();
    }
}

単体テストを実行すると、ctsにはTempCsvFileVerificationCancellationの値が割り当てられます。sourceのTokenプロパティは、Source.Tokenを返します。私が間違ったことをしたことについて途方に暮れています。

任意のポインタ/支援をいただければ幸いです。

ありがとう

編集

4

1 に答える 1

3

最初はうまくいくように見えますが、うまくいかないので試してみてください:

検証の一致条件をIt.IsAny()、It.IsAny()に変更して、それが呼び出されるかどうかを確認します。- そうでない場合は、コードをデバッグして何が起こっているかを確認します - 一致する場合は、一致の問題です

entity.Object、It.IsAny()を試して 、UserInputEntity が間違っているかどうかを確認してください。

UserInputEntity に問題がない場合は、ソース セットアップにコールバックを配置します。何もする必要はありませんが、SetupCsvFileVerification が呼び出されたときにどの値が使用されているかを確認できます。

更新
私はそれを見つけたと思います、そしてそれは以下の私のポイントの1つに関連しています. ctsを値に初期化します。セットアップのため、初期値が必要です。

source.SetupGet(x => x.Source).Returns(cts); 
source.SetupGet(x => x.Token).Returns(cts.Token); 

cts.Token をすぐに評価するため、これがないと失敗します。これは、本番コードで定義された (コールバックを使用して格納された)トークンではなく、テストで定義された CancellationTokenSource からトークンを返すことを意味します。

新しい cts 値を確実に使用するには、セットアップを次のように変更する必要があります。

source.SetupGet(x => x.Source).Returns(() => cts);
source.SetupGet(x => x.Token).Returns(() => cts.Token);

これは、セットからのコールバックが実行されるまで、つまり使用されるまで評価を延期します。

追加内容
問題は評価のタイミング

テスト設定で、トークン A を持つ cts X を作成するとします。
次に、cts を返すように Source を設定し、cts.Token を返すようにトークンを設定します。
これらは評価され、gets は X と A を返すように指示されます。

実行中、cts はコールバックを使用して 1 つのセットによって上書きされ (B のトークンで Y と呼びます)、Verify が使用するのは B 値であるため、失敗します。


ラムダを使用するようにセットアップを変更することで、「呼び出されたときに cts が指している値は何でも」使用するように指示しているため、シーケンスは次のようになります。

get をセットアップする - CTS またはトークン値を評価しない 検証を呼び出す
- コールバックを使用して cts を設定する
- ソースを取得する => 評価し、新しく設定した値を使用する (Y)
- トークンを取得する => 評価する、新しく設定した値を使用する (B)
確認する => 比較するBに対して、パス

その他のアイデア

CancellationTokenSource はテストをサポートするためだけに存在しますか?

その場合、別のアプローチとして、これを新しい CancellationTokenSource();を置き換えるICancellationTokenProviderに置き換えてみてください。本番コードを呼び出します。これにより、特定の CancellationToken をコードに簡単に挿入して、SetupCsvFileVerification() を検証できます。

些細な疑問 - 自由に無視

また、厳密な動作を使用していない限り、セットアップ

verify.Setup(x => x.SetupCsvFileVerification(It.IsAny<UserInputEntity>(), 
                                             It.IsAny<CancellationToken>()));

余分です。何も返さないため、スタブとしては役に立たず、後で呼び出しを明示的に検証しています。

同様に、値への 'cts' の初期化は必要ありません。ソースを設定する際のコールバックが値を入力する必要があるため、null に設定するだけで十分です。

于 2012-09-05T08:37:10.323 に答える