如何在Bot Framework C#中对含附件、按钮的对话进行单元测试
Great question—testing rich responses like attachments and buttons does require a bit more setup than plain text, but it’s totally doable with the tools already available in the .NET SDK v3. Let’s walk through how to extend your existing unit tests to cover these cases.
First, assuming you’re using DialogTestClient (the recommended approach for v3 dialog testing), you’ll need to adjust your test assertions to check beyond just the text content of the bot’s response. Here’s how to tackle common scenarios:
1. Testing Responses with Attachments
If your dialog sends file attachments (like images or PDFs), you can verify their details by inspecting the Attachments property of the returned Activity.
Example Test Case in Your Dictionary
Structure your test dictionary to include expected attachment metadata alongside text:
var testCases = new Dictionary<string, object> { // Your existing plain text test case ["Hello"] = "Hi there!", // Test case for an image attachment ["Send me an image"] = new { ExpectedText = "Here's your requested image:", ExpectedAttachments = new List<Attachment> { new Attachment { ContentType = "image/png", ContentUrl = "https://example.com/sample-image.png", Name = "sample-image.png" } } } };
Asserting the Attachment
In your test method, validate the attachment after receiving the bot’s response:
var response = await client.SendActivityAsync<IMessageActivity>(testInput); var expectedData = testCases[testInput] as dynamic; // Check the response text first Assert.Equal(expectedData.ExpectedText, response.Text); // Verify the attachment exists and matches expected values Assert.NotEmpty(response.Attachments); var actualAttachment = response.Attachments.First(); var expectedAttachment = expectedData.ExpectedAttachments[0]; Assert.Equal(expectedAttachment.ContentType, actualAttachment.ContentType); Assert.Equal(expectedAttachment.ContentUrl, actualAttachment.ContentUrl); Assert.Equal(expectedAttachment.Name, actualAttachment.Name);
2. Testing Responses with Buttons (Rich Cards)
For interactive elements like buttons on HeroCards or ThumbnailCards, you’ll need to deserialize the attachment content into the appropriate card type and check its actions.
Example Test Case for a HeroCard with Buttons
Update your dictionary to include expected card action details:
["Show options"] = new { ExpectedText = "Please choose an option:", ExpectedCardActions = new List<CardAction> { new CardAction { Type = ActionTypes.ImBack, Title = "Option 1", Value = "select-option-1" }, new CardAction { Type = ActionTypes.ImBack, Title = "Option 2", Value = "select-option-2" } } };
Asserting the Card Actions
In your test, deserialize the card content to validate the buttons:
var response = await client.SendActivityAsync<IMessageActivity>(testInput); var expectedData = testCases[testInput] as dynamic; // Locate the HeroCard attachment var heroCardAttachment = response.Attachments.FirstOrDefault(a => a.ContentType == HeroCard.ContentType); Assert.NotNull(heroCardAttachment); // Deserialize the content to a HeroCard object var heroCard = JsonConvert.DeserializeObject<HeroCard>(heroCardAttachment.Content.ToString()); Assert.NotNull(heroCard); // Compare each expected action to the actual card actions var expectedActions = expectedData.ExpectedCardActions.ToObject<List<CardAction>>(); for (int i = 0; i < expectedActions.Count; i++) { var expectedAction = expectedActions[i]; var actualAction = heroCard.Actions[i]; Assert.Equal(expectedAction.Type, actualAction.Type); Assert.Equal(expectedAction.Title, actualAction.Title); Assert.Equal(expectedAction.Value, actualAction.Value); }
Key Notes for .NET SDK v3
- Ensure you’re referencing
Microsoft.Bot.ConnectorandNewtonsoft.Json(v3 relies heavily on Newtonsoft for serialization). - Use the emulator’s "Inspect" tab to view the raw JSON of bot responses—this helps you get exact values for your assertions (like content URLs or action values).
- For complex cards, create helper methods to compare card properties to avoid repetitive assertion code.
This approach should let you extend your existing test suite to cover all rich response types your dialogs send. Let me know if you need help adapting this to your specific scenario!
内容的提问来源于stack exchange,提问作者Emiliano Montesdeoca

