Bot Builder v4.5 のユニットテスト : ダイアログクラスのテスト - CancelAndHelpDialog 

[前回](https://qiita.com/kenakamu/items/147919f508a489e6630e) は BookingDialog のテストを見ていきましたが、今回は CancelAndHelpDialog のテストを見ていきます。

# CancelAndHelpDialog

このダイアログでは、主に以下の処理を行います。

- cancel、quit が来たら現在のダイアログをキャンセル
- help、? が来たらヘルプを表示してダイアログを継続

では早速テストを見ていきます。

# CancelAndHelpDialogTests コンストラクタ

CancelAndHelpDialogTests クラス内で実行するテストに共通するものをコンストラクタで準備します。

```csharp
private readonly IMiddleware[] _middlewares;

public CancelAndHelpDialogTests(ITestOutputHelper output)
    : base(output)
{
    _middlewares = new IMiddleware[] { new XUnitDialogTestLogger(output) };
}
```

# ShouldBeAbleToCancel テスト

このテストでは cancel または quite が遅れた場合の処理をテストします。

```csharp:CancelAndHelpDialogTests.cs
[Theory]
[InlineData("cancel")]
[InlineData("quit")]
public async Task ShouldBeAbleToCancel(string cancelUtterance)
{
    var sut = new TestCancelAndHelpDialog();
    var testClient = new DialogTestClient(Channels.Test, sut, middlewares: _middlewares);

    // Execute the test case
    var reply = await testClient.SendActivityAsync<IMessageActivity>("Hi");
    Assert.Equal("Hi there", reply.Text);
    Assert.Equal(DialogTurnStatus.Waiting, testClient.DialogTurnResult.Status);

    reply = await testClient.SendActivityAsync<IMessageActivity>(cancelUtterance);
    Assert.Equal("Cancelling...", reply.Text);
    Assert.Equal(DialogTurnStatus.Complete, testClient.DialogTurnResult.Status);
}
```

## テストパターンの作成

今回も Theory テストですが、 前回よりパターンが複雑でないため、 InlineData を使っています。

## ダミーダイアログ

キャンセルフローを試すことが目的のため、実際に利用する MainDialog や BookingDialog ではなく、テスト用にダイアログを作成しています。

```csharp
private class TestCancelAndHelpDialog : CancelAndHelpDialog
{
    public TestCancelAndHelpDialog()
        : base(nameof(TestCancelAndHelpDialog))
    {
        AddDialog(new TextPrompt(nameof(TextPrompt)));
        var steps = new WaterfallStep[]
        {
            PromptStep,
            FinalStep,
        };
        AddDialog(new WaterfallDialog("testWaterfall", steps));
        InitialDialogId = "testWaterfall";
    }

    private async Task<DialogTurnResult> PromptStep(WaterfallStepContext stepContext, CancellationToken cancellationToken)
    {
        return await stepContext.PromptAsync(nameof(TextPrompt), new PromptOptions { Prompt = MessageFactory.Text("Hi there") }, cancellationToken);
    }

    private Task<DialogTurnResult> FinalStep(WaterfallStepContext stepContext, CancellationToken cancellationToken)
    {
        throw new NotImplementedException();
    }
}
```

## テストの実行と結果の確認

今回も DialogTestClient を使ってテストを実行します。テスト用に用意した TestCancelAndHelpDialog ダイアログをインスタンス化して、まずは "Hi" と送信して会話を開始します。またダイアログの状態を検証しています。

```csharp
var sut = new TestCancelAndHelpDialog();
var testClient = new DialogTestClient(Channels.Test, sut, middlewares: _middlewares);

// Execute the test case
var reply = await testClient.SendActivityAsync<IMessageActivity>("Hi");
Assert.Equal("Hi there", reply.Text);
Assert.Equal(DialogTurnStatus.Waiting, testClient.DialogTurnResult.Status);
```

次に inlineData で渡されたキャンセルフレーズを送って、その応答とダイアログのステータスを確認します。

```csharp
reply = await testClient.SendActivityAsync<IMessageActivity>(cancelUtterance);
Assert.Equal("Cancelling...", reply.Text);
Assert.Equal(DialogTurnStatus.Complete, testClient.DialogTurnResult.Status);
```

テストエクスプローラーで確認すると、それぞれの結果が出ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/5c2221c4-923a-5607-6a56-e5b3490d0809.png)

# ShouldBeAbleToGetHelp テスト

基本的な流れは同じですが、テストの実行と確認では、最後のダイアログステータスが Complete ではなく引き続き元のダイアログを実行できる状態である Waiting になっているかを確認しています。

# まとめ

今回はより簡単なテストケースの作成方法として InlineData を使う方法を見ていきました。こちらの記事を先にした方が良かった気もしますが、時すでに遅しです。次回は DateResolverDialog のテストを見ていきます。

[次の記事へ](https://qiita.com/kenakamu/items/82b3f26e10457481016b)
[目次へ戻る](https://qiita.com/kenakamu/items/6dc043cfc1f199032883)