First pass a TestBot unit tests
This commit is contained in:
Родитель
a9705e1104
Коммит
f0f243277e
|
@ -82,6 +82,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Testi
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.Testing.Tests", "tests\Microsoft.Bot.Builder.Testing.Tests\Microsoft.Bot.Builder.Testing.Tests.csproj", "{E4E13301-9193-4106-B0E3-41276B478E7C}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Builder.TestBot.Tests", "tests\Microsoft.Bot.Builder.TestBot.Tests\Microsoft.Bot.Builder.TestBot.Tests.csproj", "{76391566-9F22-4994-8B0F-02EFC0E9E228}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug - NuGet Packages|Any CPU = Debug - NuGet Packages|Any CPU
|
||||
|
@ -361,6 +363,14 @@ Global
|
|||
{E4E13301-9193-4106-B0E3-41276B478E7C}.Documentation|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E4E13301-9193-4106-B0E3-41276B478E7C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E4E13301-9193-4106-B0E3-41276B478E7C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{76391566-9F22-4994-8B0F-02EFC0E9E228}.Debug - NuGet Packages|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{76391566-9F22-4994-8B0F-02EFC0E9E228}.Debug - NuGet Packages|Any CPU.Build.0 = Debug|Any CPU
|
||||
{76391566-9F22-4994-8B0F-02EFC0E9E228}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{76391566-9F22-4994-8B0F-02EFC0E9E228}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{76391566-9F22-4994-8B0F-02EFC0E9E228}.Documentation|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{76391566-9F22-4994-8B0F-02EFC0E9E228}.Documentation|Any CPU.Build.0 = Debug|Any CPU
|
||||
{76391566-9F22-4994-8B0F-02EFC0E9E228}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{76391566-9F22-4994-8B0F-02EFC0E9E228}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -403,6 +413,7 @@ Global
|
|||
{B9DDC8CB-8EDF-4D98-913A-22F19E642223} = {8667F820-8ADA-4498-91AE-AE95DEE5227E}
|
||||
{060F070A-BBFA-490E-BE89-3844C857B771} = {4269F3C3-6B42-419B-B64A-3E6DC0F1574A}
|
||||
{E4E13301-9193-4106-B0E3-41276B478E7C} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
|
||||
{76391566-9F22-4994-8B0F-02EFC0E9E228} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {7173C9F3-A7F9-496E-9078-9156E35D6E16}
|
||||
|
|
|
@ -100,7 +100,7 @@ namespace Microsoft.Bot.Builder.Testing
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets and returns the next bot response./>.
|
||||
/// Gets the next bot response./>.
|
||||
/// </summary>
|
||||
/// <returns>The next activity in the queue; or null, if the queue is empty.</returns>
|
||||
/// <typeparam name="T">An <see cref="IActivity"/> derived type.</typeparam>
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<WarningsAsErrors />
|
||||
<DocumentationFile />
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
|
@ -26,7 +27,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<DocumentationFile>C:\Projects\Repos\botbuilder-dotnet\libraries\Microsoft.Bot.Builder.Testing\Microsoft.Bot.Builder.Testing.xml</DocumentationFile>
|
||||
<DocumentationFile></DocumentationFile>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<WarningsAsErrors />
|
||||
</PropertyGroup>
|
||||
|
@ -34,11 +35,13 @@
|
|||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Documentation|AnyCPU'">
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<WarningsAsErrors />
|
||||
<DocumentationFile />
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug - NuGet Packages|AnyCPU'">
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<WarningsAsErrors />
|
||||
<DocumentationFile />
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RuleSet Name="Rules for StyleCop.Analyzers" Description="Code analysis rules for StyleCop.Analyzers.csproj." ToolsVersion="14.0">
|
||||
<Rules AnalyzerId="AsyncUsageAnalyzers" RuleNamespace="AsyncUsageAnalyzers">
|
||||
<Rule Id="UseConfigureAwait" Action="Warning" />
|
||||
<Rule Id="AvoidAsyncVoid" Action="Warning" />
|
||||
</Rules>
|
||||
<Rules AnalyzerId="Microsoft.CodeAnalysis.CSharp.Features" RuleNamespace="Microsoft.CodeAnalysis.CSharp.Features">
|
||||
<Rule Id="IDE0003" Action="None" />
|
||||
</Rules>
|
||||
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers">
|
||||
<Rule Id="SA1101" Action="None" /> <!-- local calls prefixed with this -->
|
||||
<Rule Id="SA1129" Action="None" /> <!-- don't use value type constructor-->
|
||||
<Rule Id="SA1200" Action="None" />
|
||||
<Rule Id="SA1214" Action ="None"/> <!-- encapsalate field in property-->
|
||||
<Rule Id="SA1305" Action="Warning" />
|
||||
<Rule Id="SA1309" Action="None" />
|
||||
<Rule Id="SA1412" Action="Warning" />
|
||||
<Rule Id="SA1600" Action="None" />
|
||||
<Rule Id="SA1609" Action="Warning" />
|
||||
<Rule Id="SA1633" Action="None" />
|
||||
</Rules>
|
||||
</RuleSet>
|
|
@ -1,159 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<doc>
|
||||
<assembly>
|
||||
<name>Microsoft.Bot.Builder.Testing</name>
|
||||
</assembly>
|
||||
<members>
|
||||
<member name="T:Microsoft.Bot.Builder.Testing.DialogTestClient">
|
||||
<summary>
|
||||
A client to for testing dialogs in isolation.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Testing.DialogTestClient.#ctor(System.String,Microsoft.Bot.Builder.Dialogs.Dialog,System.Object,System.Collections.Generic.IEnumerable{Microsoft.Bot.Builder.IMiddleware},Microsoft.Bot.Builder.BotCallbackHandler)">
|
||||
<summary>
|
||||
Initializes a new instance of the <see cref="T:Microsoft.Bot.Builder.Testing.DialogTestClient"/> class.
|
||||
</summary>
|
||||
<param name="channelId">
|
||||
The channelId (see <see cref="T:Microsoft.Bot.Connector.Channels"/>) to be used for the test.
|
||||
Use <see cref="F:Microsoft.Bot.Connector.Channels.Emulator"/> or <see cref="F:Microsoft.Bot.Connector.Channels.Test"/> if you are uncertain of the channel you are targeting.
|
||||
Otherwise, it is recommended that you use the id for the channel(s) your bot will be using.
|
||||
Consider writing a test case for each channel.
|
||||
</param>
|
||||
<param name="targetDialog">The dialog to be tested. This will be the root dialog for the test client.</param>
|
||||
<param name="initialDialogOptions">(Optional) additional argument(s) to pass to the dialog being started.</param>
|
||||
<param name="middlewares">(Optional) A list of middlewares to be added to the test adapter.</param>
|
||||
<param name="callback">(Optional) The bot turn processing logic for the test. If this value is not provided, the test client will create a default <see cref="T:Microsoft.Bot.Builder.BotCallbackHandler"/>.</param>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Testing.DialogTestClient.#ctor(Microsoft.Bot.Builder.Adapters.TestAdapter,Microsoft.Bot.Builder.Dialogs.Dialog,System.Object,System.Collections.Generic.IEnumerable{Microsoft.Bot.Builder.IMiddleware},Microsoft.Bot.Builder.BotCallbackHandler)">
|
||||
<summary>
|
||||
Initializes a new instance of the <see cref="T:Microsoft.Bot.Builder.Testing.DialogTestClient"/> class.
|
||||
</summary>
|
||||
<param name="testAdapter">The <see cref="T:Microsoft.Bot.Builder.Adapters.TestAdapter"/> to use.</param>
|
||||
<param name="targetDialog">The dialog to be tested. This will be the root dialog for the test client.</param>
|
||||
<param name="initialDialogOptions">(Optional) additional argument(s) to pass to the dialog being started.</param>
|
||||
<param name="middlewares">(Optional) A list of middlewares to be added to the test adapter.</param>
|
||||
<param name="callback">(Optional) The bot turn processing logic for the test. If this value is not provided, the test client will create a default <see cref="T:Microsoft.Bot.Builder.BotCallbackHandler"/>.</param>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Testing.DialogTestClient.DialogTurnResult">
|
||||
<summary>
|
||||
Gets the latest <see cref="P:Microsoft.Bot.Builder.Testing.DialogTestClient.DialogTurnResult"/> for the dialog being tested.
|
||||
</summary>
|
||||
<value>A <see cref="P:Microsoft.Bot.Builder.Testing.DialogTestClient.DialogTurnResult"/> instance with the result of the last turn.</value>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Testing.DialogTestClient.SendActivityAsync``1(Microsoft.Bot.Schema.Activity,System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
Sends an <see cref="T:Microsoft.Bot.Schema.Activity"/> to the target dialog.
|
||||
</summary>
|
||||
<param name="activity">The activity to send.</param>
|
||||
<param name="cancellationToken">The cancellation token.</param>
|
||||
<returns>A <see cref="T:System.Threading.Tasks.Task"/> representing the result of the asynchronous operation.</returns>
|
||||
<typeparam name="T">An <see cref="T:Microsoft.Bot.Schema.IActivity"/> derived type.</typeparam>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Testing.DialogTestClient.SendActivityAsync``1(System.String,System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
Sends a message activity to to the target dialog.
|
||||
</summary>
|
||||
<param name="text">The text of the message to send.</param>
|
||||
<param name="cancellationToken">The cancellation token.</param>
|
||||
<returns>A <see cref="T:System.Threading.Tasks.Task"/> representing the result of the asynchronous operation.</returns>
|
||||
<typeparam name="T">An <see cref="T:Microsoft.Bot.Schema.IActivity"/> derived type.</typeparam>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Testing.DialogTestClient.GetNextReply``1">
|
||||
<summary>
|
||||
Gets and returns the next bot response./>.
|
||||
</summary>
|
||||
<returns>The next activity in the queue; or null, if the queue is empty.</returns>
|
||||
<typeparam name="T">An <see cref="T:Microsoft.Bot.Schema.IActivity"/> derived type.</typeparam>
|
||||
</member>
|
||||
<member name="T:Microsoft.Bot.Builder.Testing.XUnit.TestDataObject">
|
||||
<summary>
|
||||
A wrapper class for XUnit test data that enables support for enumerating test cases in Test Explorer.
|
||||
</summary>
|
||||
<remarks>
|
||||
VS Test explorer only supports value types for data driven tests.
|
||||
This class implements <see cref="T:Xunit.Abstractions.IXunitSerializable"/> and serializes complex types as json
|
||||
so the test cases can be enumerated and displayed into VS test explorer.
|
||||
This also allows the developer to right click on a particular test case on VS Test explorer and run it individually.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Testing.XUnit.TestDataObject.#ctor(System.Object)">
|
||||
<summary>
|
||||
Initializes a new instance of the <see cref="T:Microsoft.Bot.Builder.Testing.XUnit.TestDataObject"/> class.
|
||||
</summary>
|
||||
<param name="testData">An object with the data to be used in the test.</param>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Testing.XUnit.TestDataObject.TestObject">
|
||||
<summary>
|
||||
Gets a json string with the test data object.
|
||||
</summary>
|
||||
<value>The test data object as a json string.</value>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Testing.XUnit.TestDataObject.Deserialize(Xunit.Abstractions.IXunitSerializationInfo)">
|
||||
<summary>
|
||||
Used by XUnit.net for deserialization.
|
||||
</summary>
|
||||
<param name="serializationInfo">A parameter used by XUnit.net.</param>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Testing.XUnit.TestDataObject.Serialize(Xunit.Abstractions.IXunitSerializationInfo)">
|
||||
<summary>
|
||||
Used by XUnit.net for serialization.
|
||||
</summary>
|
||||
<param name="serializationInfo">A parameter used by XUnit.net.</param>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Testing.XUnit.TestDataObject.GetObject``1">
|
||||
<summary>
|
||||
Gets the test data object for the specified .Net type.
|
||||
</summary>
|
||||
<typeparam name="T">The type of the object to be returned.</typeparam>
|
||||
<returns>The test object instance.</returns>
|
||||
</member>
|
||||
<member name="T:Microsoft.Bot.Builder.Testing.XUnit.XUnitOutputMiddleware">
|
||||
<inheritdoc />
|
||||
<summary>
|
||||
A middleware to output incoming and outgoing activities as json strings to the console during
|
||||
unit tests.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Testing.XUnit.XUnitOutputMiddleware.#ctor(Xunit.Abstractions.ITestOutputHelper)">
|
||||
<summary>
|
||||
Initializes a new instance of the <see cref="T:Microsoft.Bot.Builder.Testing.XUnit.XUnitOutputMiddleware"/> class.
|
||||
</summary>
|
||||
<remarks>
|
||||
This middleware outputs the incoming and outgoing activities for the XUnit based test to the console window.
|
||||
If you need to output the incoming and outgoing activities to some other provider consider using
|
||||
the <see cref="T:Microsoft.Bot.Builder.TranscriptLoggerMiddleware"/> instead.
|
||||
</remarks>
|
||||
<param name="xunitOutputHelper">
|
||||
An XUnit <see cref="T:Xunit.Abstractions.ITestOutputHelper"/> instance.
|
||||
See <see href="https://xunit.net/docs/capturing-output.html">Capturing Output</see> in the XUnit documentation for additional details.
|
||||
</param>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Testing.XUnit.XUnitOutputMiddleware.Output">
|
||||
<summary>
|
||||
Gets the <see cref="T:Xunit.Abstractions.ITestOutputHelper"/> instance for this middleware.
|
||||
</summary>
|
||||
<value>The <see cref="T:Xunit.Abstractions.ITestOutputHelper"/> instance for this middleware.</value>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Testing.XUnit.XUnitOutputMiddleware.LogIncomingActivityAsync(Microsoft.Bot.Builder.ITurnContext,Microsoft.Bot.Schema.Activity,System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
Logs messages sent from the user to the bot.
|
||||
</summary>
|
||||
<remarks>
|
||||
<see cref="F:Microsoft.Bot.Schema.ActivityTypes.Message"/> activities will be logged as text. Other activities will be logged as json.
|
||||
</remarks>
|
||||
<param name="context">The context object for this turn.</param>
|
||||
<param name="activity">The <see cref="T:Microsoft.Bot.Schema.Activity"/> to be logged.</param>
|
||||
<param name="cancellationToken">The cancellation token.</param>
|
||||
<returns>A task that represents the work to execute.</returns>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Testing.XUnit.XUnitOutputMiddleware.LogOutgoingActivityAsync(Microsoft.Bot.Builder.ITurnContext,Microsoft.Bot.Schema.Activity,System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
Logs messages sent from the bot to the user.
|
||||
</summary>
|
||||
<param name="context">The context object for this turn.</param>
|
||||
<param name="activity">The <see cref="T:Microsoft.Bot.Schema.Activity"/> to be logged.</param>
|
||||
<param name="cancellationToken">The cancellation token.</param>
|
||||
<returns>A task that represents the work to execute.</returns>
|
||||
</member>
|
||||
</members>
|
||||
</doc>
|
|
@ -21,6 +21,10 @@
|
|||
<Description>Library for building bots using Microsoft Bot Framework Connector</Description>
|
||||
<Summary>Library for building bots using Microsoft Bot Framework Connector</Summary>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Documentation|AnyCPU'">
|
||||
<DocumentationFile></DocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AsyncUsageAnalyzers" Version="1.0.0-alpha003" PrivateAssets="all" />
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Adapters;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Connector;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.BotBuilderSamples.Tests.Framework;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Bots
|
||||
{
|
||||
public class DialogAndWelcomeBotTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task ReturnsWelcomeCardOnConversationUpdate()
|
||||
{
|
||||
// Arrange
|
||||
var mockRootDialog = SimpleMockFactory.CreateMockDialog<Dialog>(null, "mockRootDialog");
|
||||
|
||||
// TODO: do we need state here?
|
||||
var memoryStorage = new MemoryStorage();
|
||||
var sut = new DialogAndWelcomeBot<Dialog>(new ConversationState(memoryStorage), new UserState(memoryStorage), mockRootDialog.Object, null);
|
||||
var conversationUpdateActivity = new Activity
|
||||
{
|
||||
Type = ActivityTypes.ConversationUpdate,
|
||||
MembersAdded = new List<ChannelAccount>
|
||||
{
|
||||
new ChannelAccount { Id = "theUser" },
|
||||
},
|
||||
Recipient = new ChannelAccount { Id = "theBot" },
|
||||
};
|
||||
var testAdapter = new TestAdapter(Channels.Test);
|
||||
|
||||
// Act
|
||||
// Note: it is kind of obscure that we need to use OnTurnAsync to trigger OnMembersAdded so we get the card
|
||||
await testAdapter.ProcessActivityAsync(conversationUpdateActivity, sut.OnTurnAsync, CancellationToken.None);
|
||||
var reply = testAdapter.GetNextReply();
|
||||
|
||||
// Assert
|
||||
var m = (IMessageActivity)reply;
|
||||
Assert.Equal(1, m.Attachments.Count);
|
||||
Assert.Equal("application/vnd.microsoft.card.adaptive", m.Attachments.FirstOrDefault()?.ContentType);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Adapters;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.BotBuilderSamples.Tests.Framework;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Bots
|
||||
{
|
||||
public class DialogBotTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task LogsInformationToILogger()
|
||||
{
|
||||
// Arrange
|
||||
var memoryStorage = new MemoryStorage();
|
||||
var conversationState = new ConversationState(memoryStorage);
|
||||
var userState = new UserState(memoryStorage);
|
||||
|
||||
var mockRootDialog = SimpleMockFactory.CreateMockDialog<Dialog>(null, "mockRootDialog");
|
||||
var mockLogger = new Mock<ILogger<DialogBot<Dialog>>>();
|
||||
mockLogger.Setup(x =>
|
||||
x.Log(It.IsAny<LogLevel>(), It.IsAny<EventId>(), It.IsAny<object>(), null, It.IsAny<Func<object, Exception, string>>()));
|
||||
|
||||
// Run the bot
|
||||
var sut = new DialogBot<Dialog>(conversationState, userState, mockRootDialog.Object, mockLogger.Object);
|
||||
var testAdapter = new TestAdapter();
|
||||
var testFlow = new TestFlow(testAdapter, sut);
|
||||
await testFlow.Send("Hi").StartTestAsync();
|
||||
|
||||
// Assert that log was changed with the expected parameters
|
||||
mockLogger.Verify(
|
||||
x => x.Log(
|
||||
LogLevel.Information,
|
||||
It.IsAny<EventId>(),
|
||||
It.Is<object>(o => o.ToString() == "Running dialog with Message Activity."),
|
||||
null,
|
||||
It.IsAny<Func<object, Exception, string>>()),
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SavesTurnStateUsingMockWithVirtualSaveChangesAsync()
|
||||
{
|
||||
// Note: this test requires that SaveChangesAsync is made virtual in order to be able to create a mock.
|
||||
var memoryStorage = new MemoryStorage();
|
||||
var mockConversationState = new Mock<ConversationState>(memoryStorage)
|
||||
{
|
||||
CallBase = true,
|
||||
};
|
||||
|
||||
var mockUserState = new Mock<UserState>(memoryStorage)
|
||||
{
|
||||
CallBase = true,
|
||||
};
|
||||
|
||||
var mockRootDialog = SimpleMockFactory.CreateMockDialog<Dialog>(null, "mockRootDialog");
|
||||
var mockLogger = new Mock<ILogger<DialogBot<Dialog>>>();
|
||||
|
||||
// Act
|
||||
var sut = new DialogBot<Dialog>(mockConversationState.Object, mockUserState.Object, mockRootDialog.Object, mockLogger.Object);
|
||||
var testAdapter = new TestAdapter();
|
||||
var testFlow = new TestFlow(testAdapter, sut);
|
||||
await testFlow.Send("Hi").StartTestAsync();
|
||||
|
||||
// Assert that SaveChangesAsync was called
|
||||
mockConversationState.Verify(x => x.SaveChangesAsync(It.IsAny<TurnContext>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Once);
|
||||
mockUserState.Verify(x => x.SaveChangesAsync(It.IsAny<TurnContext>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Once);
|
||||
}
|
||||
|
||||
[Fact(Skip = "TODO: need to figure out how to implement this version of the test")]
|
||||
public async Task SavesTurnStateUsingMemoryStorage()
|
||||
{
|
||||
// TODO: Figure out how to implement this test.
|
||||
// Note: this doesn't require a virtual SaveChangesAsync and it manually inspects storage to ensure the save methods were called.
|
||||
var memoryStorage = new MemoryStorage();
|
||||
var conversationState = new ConversationState(memoryStorage);
|
||||
var userState = new UserState(memoryStorage);
|
||||
|
||||
var mockRootDialog = new Mock<Dialog>("mockRootDialog");
|
||||
mockRootDialog.Setup(x => x.ContinueDialogAsync(It.IsAny<DialogContext>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(new DialogTurnResult(DialogTurnStatus.Empty)));
|
||||
|
||||
var mockLogger = new Mock<ILogger<DialogBot<Dialog>>>();
|
||||
|
||||
// Run the bot
|
||||
var sut = new DialogBot<Dialog>(conversationState, userState, mockRootDialog.Object, mockLogger.Object);
|
||||
var testAdapter = new TestAdapter();
|
||||
var testFlow = new TestFlow(testAdapter, sut);
|
||||
await testFlow.Send("Hi").StartTestAsync();
|
||||
|
||||
// Assert that SaveChangesAsyncWasCalled
|
||||
Assert.True(false, "TODO");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Controllers;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Integration.AspNet.Core;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Controllers
|
||||
{
|
||||
public class BotControllerTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task PostAsyncCallsProcessAsyncOnAdapter()
|
||||
{
|
||||
// Create MVC infrastructure mocks and objects
|
||||
var request = new Mock<HttpRequest>();
|
||||
var response = new Mock<HttpResponse>();
|
||||
var mockHttpContext = new Mock<HttpContext>();
|
||||
mockHttpContext.Setup(x => x.Request).Returns(request.Object);
|
||||
mockHttpContext.Setup(x => x.Response).Returns(response.Object);
|
||||
var actionContext = new ActionContext(mockHttpContext.Object, new RouteData(), new ControllerActionDescriptor());
|
||||
|
||||
// Create BF mocks
|
||||
var mockAdapter = new Mock<IBotFrameworkHttpAdapter>();
|
||||
mockAdapter
|
||||
.Setup(x => x.ProcessAsync(It.IsAny<HttpRequest>(), It.IsAny<HttpResponse>(), It.IsAny<IBot>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.CompletedTask);
|
||||
var mockBot = new Mock<IBot>();
|
||||
|
||||
// Create and initialize controller
|
||||
var sut = new BotController(mockAdapter.Object, arg => mockBot.Object)
|
||||
{
|
||||
ControllerContext = new ControllerContext(actionContext),
|
||||
};
|
||||
|
||||
// Invoke the controller
|
||||
await sut.PostAsync("doesn't matter");
|
||||
|
||||
// Assert
|
||||
mockAdapter.Verify(
|
||||
x => x.ProcessAsync(
|
||||
It.Is<HttpRequest>(o => o == request.Object),
|
||||
It.Is<HttpResponse>(o => o == response.Object),
|
||||
It.Is<IBot>(o => o == mockBot.Object),
|
||||
It.IsAny<CancellationToken>()),
|
||||
Times.Once);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests
|
||||
{
|
||||
/// <summary>
|
||||
/// A base class with helper methods and properties to test dialogs in isolation.
|
||||
/// </summary>
|
||||
public abstract class DialogTestsBase
|
||||
{
|
||||
private static readonly Lazy<IConfiguration> _configurationLazy = new Lazy<IConfiguration>(() =>
|
||||
{
|
||||
LoadLaunchSettingsIntoEnvVariables("Properties//launchSettings.json");
|
||||
|
||||
var config = new ConfigurationBuilder()
|
||||
.AddJsonFile("appsettings.json")
|
||||
.AddEnvironmentVariables();
|
||||
|
||||
return config.Build();
|
||||
});
|
||||
|
||||
protected DialogTestsBase()
|
||||
: this(null)
|
||||
{
|
||||
}
|
||||
|
||||
protected DialogTestsBase(ITestOutputHelper output)
|
||||
{
|
||||
Output = output;
|
||||
}
|
||||
|
||||
public virtual IConfiguration Configuration => _configurationLazy.Value;
|
||||
|
||||
protected ITestOutputHelper Output { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Test runners to load environment variables defined in launchSettings.json
|
||||
/// so this helper code loads it manually if the file is present.
|
||||
/// This is useful to be able to have your own key files in your local machine without
|
||||
/// having to put them in git.
|
||||
/// If you use launch settings, make sure you set the Copy to Output Directory property to Copy Always.
|
||||
/// </summary>
|
||||
/// <param name="launchSettingsFile">The relative path to the launch settings file (i.e.: "Properties//launchSettings.json")</param>
|
||||
private static void LoadLaunchSettingsIntoEnvVariables(string launchSettingsFile)
|
||||
{
|
||||
if (!File.Exists(launchSettingsFile))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using (var file = File.OpenText(launchSettingsFile))
|
||||
{
|
||||
var reader = new JsonTextReader(file);
|
||||
var fileData = JObject.Load(reader);
|
||||
|
||||
var variables = fileData
|
||||
.GetValue("profiles")
|
||||
.SelectMany(profiles => profiles.Children())
|
||||
.SelectMany(profile => profile.Children<JProperty>())
|
||||
.Where(prop => prop.Name == "environmentVariables")
|
||||
.SelectMany(prop => prop.Value.Children<JProperty>())
|
||||
.ToList();
|
||||
|
||||
foreach (var variable in variables)
|
||||
{
|
||||
Environment.SetEnvironmentVariable(variable.Name, variable.Value.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder.Testing;
|
||||
using Microsoft.Bot.Builder.Testing.XUnit;
|
||||
using Microsoft.Bot.Connector;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.BotBuilderSamples.Services;
|
||||
using Microsoft.BotBuilderSamples.Tests.Dialogs.TestData;
|
||||
using Microsoft.BotBuilderSamples.Tests.Framework;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Dialogs
|
||||
{
|
||||
public class BookingDialogTests : DialogTestsBase
|
||||
{
|
||||
private readonly XUnitOutputMiddleware[] _middlewares;
|
||||
|
||||
public BookingDialogTests(ITestOutputHelper output)
|
||||
: base(output)
|
||||
{
|
||||
_middlewares = new[] { new XUnitOutputMiddleware(output) };
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(BookingDialogTestsDataGenerator.BookingFlows), MemberType = typeof(BookingDialogTestsDataGenerator))]
|
||||
public async Task DialogFlowUseCases(TestDataObject testData)
|
||||
{
|
||||
// Arrange
|
||||
var bookingTestData = testData.GetObject<BookingDialogTestCase>();
|
||||
var mockFlightBookingService = new Mock<IFlightBookingService>();
|
||||
mockFlightBookingService
|
||||
.Setup(x => x.BookFlight(It.IsAny<BookingDetails>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(bookingTestData.FlightBookingServiceResult));
|
||||
|
||||
var mockGetBookingDetailsDialog = SimpleMockFactory.CreateMockDialog<GetBookingDetailsDialog>(bookingTestData.GetBookingDetailsDialogResult).Object;
|
||||
|
||||
var sut = new BookingDialog(mockGetBookingDetailsDialog, mockFlightBookingService.Object);
|
||||
var testClient = new DialogTestClient(Channels.Test, sut, middlewares: _middlewares);
|
||||
|
||||
// Act/Assert
|
||||
Output.WriteLine($"Test Case: {bookingTestData.Name}");
|
||||
for (var i = 0; i < bookingTestData.UtterancesAndReplies.GetLength(0); i++)
|
||||
{
|
||||
var message = bookingTestData.UtterancesAndReplies[i, 0];
|
||||
IMessageActivity reply;
|
||||
if (!string.IsNullOrEmpty(message))
|
||||
{
|
||||
reply = await testClient.SendActivityAsync<IMessageActivity>(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
reply = testClient.GetNextReply<IMessageActivity>();
|
||||
}
|
||||
|
||||
Assert.Equal(bookingTestData.UtterancesAndReplies[i, 1], reply.Text);
|
||||
}
|
||||
|
||||
Assert.Equal(bookingTestData.ExpectedDialogResult.Status, testClient.DialogTurnResult.Status);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Builder.Testing;
|
||||
using Microsoft.Bot.Builder.Testing.XUnit;
|
||||
using Microsoft.Bot.Connector;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Dialogs
|
||||
{
|
||||
public class CancelAndHelpDialogTests : DialogTestsBase
|
||||
{
|
||||
private readonly XUnitOutputMiddleware[] _middlewares;
|
||||
|
||||
public CancelAndHelpDialogTests(ITestOutputHelper output)
|
||||
: base(output)
|
||||
{
|
||||
_middlewares = new[] { new XUnitOutputMiddleware(output) };
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("hi", "Hi there", "cancel")]
|
||||
[InlineData("hi", "Hi there", "quit")]
|
||||
public async Task ShouldBeAbleToCancel(string utterance, string response, string cancelUtterance)
|
||||
{
|
||||
var sut = new TestCancelAndHelpDialog();
|
||||
var testClient = new DialogTestClient(Channels.Test, sut, middlewares: _middlewares);
|
||||
|
||||
var reply = await testClient.SendActivityAsync<IMessageActivity>(utterance);
|
||||
Assert.Equal(response, reply.Text);
|
||||
Assert.Equal(DialogTurnStatus.Waiting, testClient.DialogTurnResult.Status);
|
||||
|
||||
reply = await testClient.SendActivityAsync<IMessageActivity>(cancelUtterance);
|
||||
Assert.Equal("Cancelling", reply.Text);
|
||||
Assert.Equal(DialogTurnStatus.Cancelled, testClient.DialogTurnResult.Status);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("hi", "Hi there", "help")]
|
||||
[InlineData("hi", "Hi there", "?")]
|
||||
public async Task ShouldBeAbleToGetHelp(string utterance, string response, string cancelUtterance)
|
||||
{
|
||||
var sut = new TestCancelAndHelpDialog();
|
||||
var testClient = new DialogTestClient(Channels.Test, sut, middlewares: _middlewares);
|
||||
|
||||
var reply = await testClient.SendActivityAsync<IMessageActivity>(utterance);
|
||||
Assert.Equal(response, reply.Text);
|
||||
Assert.Equal(DialogTurnStatus.Waiting, testClient.DialogTurnResult.Status);
|
||||
|
||||
reply = await testClient.SendActivityAsync<IMessageActivity>(cancelUtterance);
|
||||
Assert.Equal("Show Help...", reply.Text);
|
||||
Assert.Equal(DialogTurnStatus.Waiting, testClient.DialogTurnResult.Status);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A concrete instance of <see cref="CancelAndHelpDialog"/> for testing.
|
||||
/// </summary>
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder.Testing;
|
||||
using Microsoft.Bot.Builder.Testing.XUnit;
|
||||
using Microsoft.Bot.Connector;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.BotBuilderSamples.Tests.Dialogs.TestData;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Dialogs
|
||||
{
|
||||
public class DateResolverDialogTests : DialogTestsBase
|
||||
{
|
||||
public DateResolverDialogTests(ITestOutputHelper output)
|
||||
: base(output)
|
||||
{
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(DateResolverDialogTestsDataGenerator.DateResolverCases), MemberType = typeof(DateResolverDialogTestsDataGenerator))]
|
||||
public async Task DialogFlowTests(TestDataObject testData)
|
||||
{
|
||||
// Arrange
|
||||
var testCaseData = testData.GetObject<DateResolverDialogTestCase>();
|
||||
var sut = new DateResolverDialog();
|
||||
var testClient = new DialogTestClient(Channels.Test, sut, testCaseData.InitialData, new[] { new XUnitOutputMiddleware(Output) });
|
||||
|
||||
// Act/Assert
|
||||
Output.WriteLine($"Test Case: {testCaseData.Name}");
|
||||
Output.WriteLine($"\r\nDialog Input: {testCaseData.InitialData}");
|
||||
for (var i = 0; i < testCaseData.UtterancesAndReplies.GetLength(0); i++)
|
||||
{
|
||||
var reply = await testClient.SendActivityAsync<IMessageActivity>(testCaseData.UtterancesAndReplies[i, 0]);
|
||||
Assert.Equal(testCaseData.UtterancesAndReplies[i, 1], reply?.Text);
|
||||
}
|
||||
|
||||
Output.WriteLine($"\r\nDialog result: {testClient.DialogTurnResult.Result}");
|
||||
Assert.Equal(testCaseData.ExpectedResult, testClient.DialogTurnResult.Result);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Builder.Testing;
|
||||
using Microsoft.Bot.Builder.Testing.XUnit;
|
||||
using Microsoft.Bot.Connector;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.BotBuilderSamples.Tests.Dialogs.TestData;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Dialogs
|
||||
{
|
||||
public class GetBookingDetailsDialogTests : DialogTestsBase
|
||||
{
|
||||
public GetBookingDetailsDialogTests(ITestOutputHelper output)
|
||||
: base(output)
|
||||
{
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(GetBookingDetailsDialogTestsDataGenerator.BookingFlows), MemberType = typeof(GetBookingDetailsDialogTestsDataGenerator))]
|
||||
[MemberData(nameof(GetBookingDetailsDialogTestsDataGenerator.CancelFlows), MemberType = typeof(GetBookingDetailsDialogTestsDataGenerator))]
|
||||
public async Task DialogFlowUseCases(TestDataObject testData)
|
||||
{
|
||||
// Arrange
|
||||
var bookingTestData = testData.GetObject<GetBookingDetailsDialogTestCase>();
|
||||
var sut = new GetBookingDetailsDialog();
|
||||
var testClient = new DialogTestClient(Channels.Test, sut, bookingTestData.InitialBookingDetails, new[] { new XUnitOutputMiddleware(Output) });
|
||||
|
||||
// Act/Assert
|
||||
Output.WriteLine($"Test Case: {bookingTestData.Name}");
|
||||
for (var i = 0; i < bookingTestData.UtterancesAndReplies.GetLength(0); i++)
|
||||
{
|
||||
var reply = await testClient.SendActivityAsync<IMessageActivity>(bookingTestData.UtterancesAndReplies[i, 0]);
|
||||
Assert.Equal(bookingTestData.UtterancesAndReplies[i, 1], reply?.Text);
|
||||
}
|
||||
|
||||
if (testClient.DialogTurnResult.Status == DialogTurnStatus.Cancelled)
|
||||
{
|
||||
Assert.Null(testClient.DialogTurnResult.Result);
|
||||
}
|
||||
else
|
||||
{
|
||||
var bookingResults = (BookingDetails)testClient.DialogTurnResult.Result;
|
||||
Assert.Equal(bookingTestData.ExpectedBookingDetails.Origin, bookingResults.Origin);
|
||||
Assert.Equal(bookingTestData.ExpectedBookingDetails.Destination, bookingResults.Destination);
|
||||
Assert.Equal(bookingTestData.ExpectedBookingDetails.TravelDate, bookingResults.TravelDate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Adapters;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.BotBuilderSamples.Services;
|
||||
using Microsoft.BotBuilderSamples.Tests.Framework;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Dialogs
|
||||
{
|
||||
/// <summary>
|
||||
/// This sample uses the current classes and approach for testing bot conversations.
|
||||
/// Note: this is included just as a reference.
|
||||
/// </summary>
|
||||
public class MainDialogTestFlowTests : DialogTestsBase
|
||||
{
|
||||
[Fact(Skip = "Ignoring this one, this is just a sample on the old way of writing tests")]
|
||||
public async Task WholeEnchilada()
|
||||
{
|
||||
var mockFlightBookingService = new Mock<IFlightBookingService>();
|
||||
mockFlightBookingService.Setup(x => x.BookFlight(It.IsAny<BookingDetails>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(true));
|
||||
var mockBookingDialog = SimpleMockFactory.CreateMockDialog<BookingDialog>(null, mockFlightBookingService.Object).Object;
|
||||
var mockLogger = new Mock<ILogger<MainDialog>>();
|
||||
var sut = new MainDialog(mockLogger.Object, null, mockBookingDialog);
|
||||
|
||||
var testFlow = BuildTestFlow(sut);
|
||||
|
||||
await testFlow.Send("hi")
|
||||
.AssertReply("What can I help you with today?")
|
||||
.Send("hi")
|
||||
.AssertReply("Where would you like to travel to?")
|
||||
.Send("Bahamas")
|
||||
.AssertReply("Where are you traveling from?")
|
||||
.Send("New York")
|
||||
.AssertReply("When would you like to travel?")
|
||||
.Send("tomorrow at 5 PM")
|
||||
.AssertReply(activity =>
|
||||
{
|
||||
// TODO: I had to add the Yes No for the channelId = test, the emulator displays suggested actions instead.
|
||||
var message = (IMessageActivity)activity;
|
||||
Assert.Equal(
|
||||
"Please confirm, I have you traveling to: Bahamas from: New York on: 2019-04-18T17 (1) Yes or (2) No",
|
||||
message.Text);
|
||||
})
|
||||
.Send("Yes")
|
||||
.AssertReply("I have you booked to Bahamas from New York on tomorrow 5PM")
|
||||
.StartTestAsync();
|
||||
}
|
||||
|
||||
private static TestFlow BuildTestFlow(Dialog targetDialog)
|
||||
{
|
||||
var convoState = new ConversationState(new MemoryStorage());
|
||||
var testAdapter = new TestAdapter()
|
||||
.Use(new AutoSaveStateMiddleware(convoState));
|
||||
var dialogState = convoState.CreateProperty<DialogState>("DialogState");
|
||||
var testFlow = new TestFlow(testAdapter, async (turnContext, cancellationToken) =>
|
||||
{
|
||||
var state = await dialogState.GetAsync(turnContext, () => new DialogState(), cancellationToken);
|
||||
var dialogs = new DialogSet(dialogState);
|
||||
|
||||
dialogs.Add(targetDialog);
|
||||
|
||||
var dc = await dialogs.CreateContextAsync(turnContext, cancellationToken);
|
||||
|
||||
var results = await dc.ContinueDialogAsync(cancellationToken);
|
||||
switch (results.Status)
|
||||
{
|
||||
case DialogTurnStatus.Empty:
|
||||
await dc.BeginDialogAsync(targetDialog.Id, null, cancellationToken);
|
||||
break;
|
||||
case DialogTurnStatus.Complete:
|
||||
{
|
||||
// TODO: Dialog has ended, figure out a way of asserting that this is the case.
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
return testFlow;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Builder.Testing;
|
||||
using Microsoft.Bot.Builder.Testing.XUnit;
|
||||
using Microsoft.Bot.Connector;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.BotBuilderSamples.CognitiveModels;
|
||||
using Microsoft.BotBuilderSamples.Services;
|
||||
using Microsoft.BotBuilderSamples.Tests.Framework;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Dialogs
|
||||
{
|
||||
public class MainDialogTests : DialogTestsBase
|
||||
{
|
||||
private readonly BookingDialog _mockBookingDialog;
|
||||
private readonly Mock<IRecognizer> _mockLuisRecognizer;
|
||||
private readonly Mock<ILogger<MainDialog>> _mockLogger;
|
||||
|
||||
public MainDialogTests(ITestOutputHelper output)
|
||||
: base(output)
|
||||
{
|
||||
_mockLogger = new Mock<ILogger<MainDialog>>();
|
||||
_mockLuisRecognizer = new Mock<IRecognizer>();
|
||||
|
||||
var mockFlightBookingService = new Mock<IFlightBookingService>();
|
||||
mockFlightBookingService.Setup(x => x.BookFlight(It.IsAny<BookingDetails>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(true));
|
||||
_mockBookingDialog = SimpleMockFactory.CreateMockDialog<BookingDialog>(null, new Mock<GetBookingDetailsDialog>().Object, mockFlightBookingService.Object).Object;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DialogConstructor()
|
||||
{
|
||||
// TODO: check with the team if there's value in these types of test or if there's a better way of asserting the
|
||||
// dialog got composed properly.
|
||||
var sut = new MainDialog(_mockLogger.Object, _mockLuisRecognizer.Object, _mockBookingDialog);
|
||||
|
||||
Assert.Equal("MainDialog", sut.Id);
|
||||
Assert.IsType<TextPrompt>(sut.FindDialog("TextPrompt"));
|
||||
Assert.NotNull(sut.FindDialog("BookingDialog"));
|
||||
Assert.IsType<WaterfallDialog>(sut.FindDialog("WaterfallDialog"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ShowsMessageIfLuisNotConfigured()
|
||||
{
|
||||
// Arrange
|
||||
var sut = new MainDialog(_mockLogger.Object, null, _mockBookingDialog);
|
||||
var testClient = new DialogTestClient(Channels.Test, sut, middlewares: new[] { new XUnitOutputMiddleware(Output) });
|
||||
|
||||
// Act/Assert
|
||||
var reply = await testClient.SendActivityAsync<IMessageActivity>("hi");
|
||||
Assert.Equal("NOTE: LUIS is not configured. To enable all capabilities, add 'LuisAppId', 'LuisAPIKey' and 'LuisAPIHostName' to the appsettings.json file.", reply.Text);
|
||||
|
||||
reply = testClient.GetNextReply<IMessageActivity>();
|
||||
Assert.Equal("What can I help you with today?", reply.Text);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ShowsPromptIfLuisIsConfigured()
|
||||
{
|
||||
// Arrange
|
||||
var sut = new MainDialog(_mockLogger.Object, _mockLuisRecognizer.Object, _mockBookingDialog);
|
||||
var testClient = new DialogTestClient(Channels.Test, sut, middlewares: new[] { new XUnitOutputMiddleware(Output) });
|
||||
|
||||
// Act/Assert
|
||||
var reply = await testClient.SendActivityAsync<IMessageActivity>("hi");
|
||||
Assert.Equal("What can I help you with today?", reply.Text);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("I want to book a flight", "BookFlight", "BookingDialog mock invoked")]
|
||||
[InlineData("What's the weather like?", "GetWeather", "TODO: get weather flow here")]
|
||||
[InlineData("bananas", "None", "Sorry, I didn't get that. Please try asking in a different way (intent was None)")]
|
||||
public async Task TaskSelector(string utterance, string intent, string invokedDialogResponse)
|
||||
{
|
||||
_mockLuisRecognizer
|
||||
.Setup(x => x.RecognizeAsync<FlightBooking>(It.IsAny<ITurnContext>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(() => Task.FromResult(new FlightBooking
|
||||
{
|
||||
Intents = new Dictionary<FlightBooking.Intent, IntentScore>
|
||||
{
|
||||
{ Enum.Parse<FlightBooking.Intent>(intent), new IntentScore() { Score = 1 } },
|
||||
},
|
||||
Entities = new FlightBooking._Entities(),
|
||||
}));
|
||||
|
||||
var sut = new MainDialog(_mockLogger.Object, _mockLuisRecognizer.Object, _mockBookingDialog);
|
||||
var testClient = new DialogTestClient(Channels.Test, sut, middlewares: new[] { new XUnitOutputMiddleware(Output) });
|
||||
|
||||
var reply = await testClient.SendActivityAsync<IMessageActivity>("hi");
|
||||
Assert.Equal("What can I help you with today?", reply.Text);
|
||||
|
||||
reply = await testClient.SendActivityAsync<IMessageActivity>(utterance);
|
||||
Assert.Equal(invokedDialogResponse, reply.Text);
|
||||
|
||||
reply = testClient.GetNextReply<IMessageActivity>();
|
||||
Assert.Equal("What else can I do for you?", reply.Text);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Dialogs.TestData
|
||||
{
|
||||
public class BookingDialogTestCase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the name for the test case.
|
||||
/// </summary>
|
||||
/// <value>The test case name.</value>
|
||||
public string Name { get; set; }
|
||||
|
||||
public BookingDetails GetBookingDetailsDialogResult { get; set; }
|
||||
|
||||
public string[,] UtterancesAndReplies { get; set; }
|
||||
|
||||
public DialogTurnResult ExpectedDialogResult { get; set; }
|
||||
|
||||
public bool BookedSuccessfully { get; set; }
|
||||
|
||||
public bool FlightBookingServiceResult { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Builder.Testing.XUnit;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Dialogs.TestData
|
||||
{
|
||||
[SuppressMessage("Microsoft.StyleCop.CSharp.OrderingRules", "SA1118:ParameterMustNotSpanMultipleLines", Justification = "Ignoring to make code more readable")]
|
||||
public class BookingDialogTestsDataGenerator
|
||||
{
|
||||
public static IEnumerable<object[]> BookingFlows()
|
||||
{
|
||||
yield return BuildTestCaseObject(
|
||||
"Full flow",
|
||||
new BookingDetails
|
||||
{
|
||||
Destination = "Seattle",
|
||||
Origin = "New York",
|
||||
TravelDate = $"{DateTime.UtcNow.AddDays(1):yyyy-MM-dd}",
|
||||
},
|
||||
new[,]
|
||||
{
|
||||
{ "hi", "GetBookingDetailsDialog mock invoked" },
|
||||
{ null, $"Please confirm, I have you traveling to: Seattle from: New York on: {DateTime.UtcNow.AddDays(1):yyyy-MM-dd} (1) Yes or (2) No" },
|
||||
{ "yes", "Booking your flight, this shouldn't take long..." },
|
||||
{ null, "I have you booked to Seattle from New York on tomorrow" },
|
||||
});
|
||||
|
||||
yield return BuildTestCaseObject(
|
||||
"Full flow with 'no' at confirmation",
|
||||
new BookingDetails
|
||||
{
|
||||
Destination = "Seattle",
|
||||
Origin = "New York",
|
||||
TravelDate = $"{DateTime.UtcNow.AddDays(1):yyyy-MM-dd}",
|
||||
},
|
||||
new[,]
|
||||
{
|
||||
{ "hi", "GetBookingDetailsDialog mock invoked" },
|
||||
{ null, $"Please confirm, I have you traveling to: Seattle from: New York on: {DateTime.UtcNow.AddDays(1):yyyy-MM-dd} (1) Yes or (2) No" },
|
||||
{ "no", "OK, we can do this later" },
|
||||
});
|
||||
|
||||
yield return BuildTestCaseObject(
|
||||
"Full flow with 'cancel' at confirmation",
|
||||
new BookingDetails
|
||||
{
|
||||
Destination = "Seattle",
|
||||
Origin = "New York",
|
||||
TravelDate = $"{DateTime.UtcNow.AddDays(1):yyyy-MM-dd}",
|
||||
},
|
||||
new[,]
|
||||
{
|
||||
{ "hi", "GetBookingDetailsDialog mock invoked" },
|
||||
{ null, $"Please confirm, I have you traveling to: Seattle from: New York on: {DateTime.UtcNow.AddDays(1):yyyy-MM-dd} (1) Yes or (2) No" },
|
||||
{ "cancel", "Cancelling" },
|
||||
},
|
||||
true,
|
||||
new DialogTurnResult(DialogTurnStatus.Cancelled));
|
||||
|
||||
yield return BuildTestCaseObject(
|
||||
"Full flow with failed call to FlightBookingService",
|
||||
new BookingDetails
|
||||
{
|
||||
Destination = "Seattle",
|
||||
Origin = "New York",
|
||||
TravelDate = $"{DateTime.UtcNow.AddDays(1):yyyy-MM-dd}",
|
||||
},
|
||||
new[,]
|
||||
{
|
||||
{ "hi", "GetBookingDetailsDialog mock invoked" },
|
||||
{ null, $"Please confirm, I have you traveling to: Seattle from: New York on: {DateTime.UtcNow.AddDays(1):yyyy-MM-dd} (1) Yes or (2) No" },
|
||||
{ "yes", "Booking your flight, this shouldn't take long..." },
|
||||
{ null, "Sorry, I was unable to secure your reservation, please try another flight" },
|
||||
}, false);
|
||||
}
|
||||
|
||||
private static object[] BuildTestCaseObject(string testCaseName, BookingDetails inputBookingInfo, string[,] utterancesAndReplies, bool flightBookingServiceResult = true, DialogTurnResult expectedDialogTurnResult = null)
|
||||
{
|
||||
var testData = new BookingDialogTestCase
|
||||
{
|
||||
Name = testCaseName,
|
||||
GetBookingDetailsDialogResult = inputBookingInfo,
|
||||
UtterancesAndReplies = utterancesAndReplies,
|
||||
FlightBookingServiceResult = flightBookingServiceResult,
|
||||
ExpectedDialogResult = expectedDialogTurnResult ?? new DialogTurnResult(DialogTurnStatus.Complete),
|
||||
};
|
||||
return new object[] { new TestDataObject(testData) };
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Dialogs.TestData
|
||||
{
|
||||
public class DateResolverDialogTestCase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the name for the test case.
|
||||
/// </summary>
|
||||
/// <value>The test case name.</value>
|
||||
public string Name { get; set; }
|
||||
|
||||
public string InitialData { get; set; }
|
||||
|
||||
public string ExpectedResult { get; set; }
|
||||
|
||||
public string[,] UtterancesAndReplies { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Microsoft.Bot.Builder.Testing.XUnit;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Dialogs.TestData
|
||||
{
|
||||
[SuppressMessage("Microsoft.StyleCop.CSharp.OrderingRules", "SA1118:ParameterMustNotSpanMultipleLines", Justification = "Ignoring to make code more readable")]
|
||||
|
||||
public class DateResolverDialogTestsDataGenerator
|
||||
{
|
||||
public static IEnumerable<object[]> DateResolverCases()
|
||||
{
|
||||
yield return BuildTestCaseObject(
|
||||
"tomorrow",
|
||||
null,
|
||||
$"{DateTime.UtcNow.AddDays(1):yyyy-MM-dd}",
|
||||
new[,]
|
||||
{
|
||||
{ "hi", "When would you like to travel?" },
|
||||
{ "tomorrow", null },
|
||||
});
|
||||
|
||||
yield return BuildTestCaseObject(
|
||||
"the day after tomorrow",
|
||||
null,
|
||||
$"{DateTime.UtcNow.AddDays(2):yyyy-MM-dd}",
|
||||
new[,]
|
||||
{
|
||||
{ "hi", "When would you like to travel?" },
|
||||
{ "the day after tomorrow", null },
|
||||
});
|
||||
|
||||
yield return BuildTestCaseObject(
|
||||
"two days from now",
|
||||
null,
|
||||
$"{DateTime.UtcNow.AddDays(2):yyyy-MM-dd}",
|
||||
new[,]
|
||||
{
|
||||
{ "hi", "When would you like to travel?" },
|
||||
{ "two days from now", null },
|
||||
});
|
||||
|
||||
yield return BuildTestCaseObject(
|
||||
"valid input given (tomorrow)",
|
||||
$"{DateTime.UtcNow.AddDays(1):yyyy-MM-dd}",
|
||||
$"{DateTime.UtcNow.AddDays(1):yyyy-MM-dd}",
|
||||
new[,]
|
||||
{
|
||||
{ "hi", null },
|
||||
});
|
||||
|
||||
yield return BuildTestCaseObject(
|
||||
"retry prompt",
|
||||
null,
|
||||
$"{DateTime.UtcNow.AddDays(1):yyyy-MM-dd}",
|
||||
new[,]
|
||||
{
|
||||
{ "hi", "When would you like to travel?" },
|
||||
{ "bananas", "I'm sorry, to make your booking please enter a full travel date including Day Month and Year." },
|
||||
{ "tomorrow", null },
|
||||
});
|
||||
|
||||
yield return BuildTestCaseObject(
|
||||
"fuzzy time ",
|
||||
null,
|
||||
$"2055-05-05",
|
||||
new[,]
|
||||
{
|
||||
{ "hi", "When would you like to travel?" },
|
||||
{ "may 5th", "I'm sorry, to make your booking please enter a full travel date including Day Month and Year." },
|
||||
{ "may 5th 2055", null },
|
||||
});
|
||||
}
|
||||
|
||||
private static object[] BuildTestCaseObject(string testCaseName, string input, string result, string[,] utterancesAndReplies)
|
||||
{
|
||||
var testData = new DateResolverDialogTestCase
|
||||
{
|
||||
Name = testCaseName,
|
||||
InitialData = input,
|
||||
ExpectedResult = result,
|
||||
UtterancesAndReplies = utterancesAndReplies,
|
||||
};
|
||||
return new object[] { new TestDataObject(testData) };
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Dialogs.TestData
|
||||
{
|
||||
public class GetBookingDetailsDialogTestCase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the name for the test case.
|
||||
/// </summary>
|
||||
/// <value>The test case name.</value>
|
||||
public string Name { get; set; }
|
||||
|
||||
public BookingDetails InitialBookingDetails { get; set; }
|
||||
|
||||
public string[,] UtterancesAndReplies { get; set; }
|
||||
|
||||
public BookingDetails ExpectedBookingDetails { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Microsoft.Bot.Builder.Testing.XUnit;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Dialogs.TestData
|
||||
{
|
||||
[SuppressMessage("Microsoft.StyleCop.CSharp.OrderingRules", "SA1118:ParameterMustNotSpanMultipleLines", Justification = "Ignoring to make code more readable")]
|
||||
public class GetBookingDetailsDialogTestsDataGenerator
|
||||
{
|
||||
public static IEnumerable<object[]> BookingFlows()
|
||||
{
|
||||
yield return BuildTestCaseObject(
|
||||
"Full flow",
|
||||
new BookingDetails(),
|
||||
new[,]
|
||||
{
|
||||
{ "hi", "Where would you like to travel to?" },
|
||||
{ "Seattle", "Where are you traveling from?" },
|
||||
{ "New York", "When would you like to travel?" },
|
||||
{ "tomorrow", null },
|
||||
},
|
||||
new BookingDetails
|
||||
{
|
||||
Destination = "Seattle",
|
||||
Origin = "New York",
|
||||
TravelDate = $"{DateTime.UtcNow.AddDays(1):yyyy-MM-dd}",
|
||||
});
|
||||
|
||||
yield return BuildTestCaseObject(
|
||||
"Destination given",
|
||||
new BookingDetails
|
||||
{
|
||||
Destination = "Bahamas",
|
||||
Origin = null,
|
||||
TravelDate = null,
|
||||
},
|
||||
new[,]
|
||||
{
|
||||
{ "hi", "Where are you traveling from?" },
|
||||
{ "New York", "When would you like to travel?" },
|
||||
{ "tomorrow", null },
|
||||
},
|
||||
new BookingDetails
|
||||
{
|
||||
Destination = "Bahamas",
|
||||
Origin = "New York",
|
||||
TravelDate = $"{DateTime.UtcNow.AddDays(1):yyyy-MM-dd}",
|
||||
});
|
||||
|
||||
yield return BuildTestCaseObject(
|
||||
"Destination and Origin given",
|
||||
new BookingDetails
|
||||
{
|
||||
Destination = "Seattle",
|
||||
Origin = "New York",
|
||||
TravelDate = null,
|
||||
},
|
||||
new[,]
|
||||
{
|
||||
{ "hi", "When would you like to travel?" },
|
||||
{ "tomorrow", null },
|
||||
},
|
||||
new BookingDetails
|
||||
{
|
||||
Destination = "Seattle",
|
||||
Origin = "New York",
|
||||
TravelDate = $"{DateTime.UtcNow.AddDays(1):yyyy-MM-dd}",
|
||||
});
|
||||
|
||||
yield return BuildTestCaseObject(
|
||||
"All booking details given for today",
|
||||
new BookingDetails
|
||||
{
|
||||
Destination = "Seattle",
|
||||
Origin = "Bahamas",
|
||||
TravelDate = $"{DateTime.UtcNow:yyyy-MM-dd}",
|
||||
},
|
||||
new[,]
|
||||
{
|
||||
{ "hi", null },
|
||||
},
|
||||
new BookingDetails
|
||||
{
|
||||
Destination = "Seattle",
|
||||
Origin = "Bahamas",
|
||||
TravelDate = $"{DateTime.UtcNow:yyyy-MM-dd}",
|
||||
});
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> CancelFlows()
|
||||
{
|
||||
yield return BuildTestCaseObject(
|
||||
"Cancel on origin prompt",
|
||||
new BookingDetails(),
|
||||
new[,]
|
||||
{
|
||||
{ "hi", "Where would you like to travel to?" },
|
||||
{ "cancel", "Cancelling" },
|
||||
},
|
||||
null);
|
||||
|
||||
yield return BuildTestCaseObject(
|
||||
"Cancel on destination prompt",
|
||||
new BookingDetails(),
|
||||
new[,]
|
||||
{
|
||||
{ "hi", "Where would you like to travel to?" },
|
||||
{ "Seattle", "Where are you traveling from?" },
|
||||
{ "cancel", "Cancelling" },
|
||||
},
|
||||
null);
|
||||
|
||||
yield return BuildTestCaseObject(
|
||||
"Cancel on date prompt",
|
||||
new BookingDetails(),
|
||||
new[,]
|
||||
{
|
||||
{ "hi", "Where would you like to travel to?" },
|
||||
{ "Seattle", "Where are you traveling from?" },
|
||||
{ "New York", "When would you like to travel?" },
|
||||
{ "cancel", "Cancelling" },
|
||||
},
|
||||
null);
|
||||
}
|
||||
|
||||
private static object[] BuildTestCaseObject(string testCaseName, BookingDetails inputBookingInfo, string[,] utterancesAndReplies, BookingDetails expectedBookingInfo)
|
||||
{
|
||||
var testData = new GetBookingDetailsDialogTestCase
|
||||
{
|
||||
Name = testCaseName,
|
||||
InitialBookingDetails = inputBookingInfo,
|
||||
UtterancesAndReplies = utterancesAndReplies,
|
||||
ExpectedBookingDetails = expectedBookingInfo,
|
||||
};
|
||||
return new object[] { new TestDataObject(testData) };
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
# Note
|
||||
This folder contains data generators and test case object definitions for Theory tests.
|
|
@ -0,0 +1,2 @@
|
|||
# Note
|
||||
This folder contains a set of helper classes and extensions that could eventually be moved to the framework.
|
|
@ -0,0 +1,43 @@
|
|||
using System.Threading;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.AI.Luis;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Recognizers.Text;
|
||||
using Moq;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Framework
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains utility methods for creating simple mock objects based on <see href="http://stackoverflow.com">moq</see>/>.
|
||||
/// </summary>
|
||||
public static class SimpleMockFactory
|
||||
{
|
||||
// Creates a simple mock dialog.
|
||||
public static Mock<T> CreateMockDialog<T>(object expectedResult = null, params object[] constructorParams)
|
||||
where T : Dialog
|
||||
{
|
||||
var mockDialog = new Mock<T>(constructorParams);
|
||||
var mockDialogNameTypeName = typeof(T).Name;
|
||||
mockDialog
|
||||
.Setup(x => x.BeginDialogAsync(It.IsAny<DialogContext>(), It.IsAny<object>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(async (DialogContext dialogContext, object options, CancellationToken cancellationToken) =>
|
||||
{
|
||||
await dialogContext.Context.SendActivityAsync($"{mockDialogNameTypeName} mock invoked", cancellationToken: cancellationToken);
|
||||
|
||||
return await dialogContext.EndDialogAsync(expectedResult, cancellationToken);
|
||||
});
|
||||
|
||||
return mockDialog;
|
||||
}
|
||||
|
||||
//public static Mock<T> CreateMockLuisRecognizer<T>(IRecognizerConvert returns)
|
||||
// where T : LuisRecognizer
|
||||
//{
|
||||
// var mockRecognizer = new Mock<T>();
|
||||
// mockRecognizer
|
||||
// .Setup(x => x.RecognizeAsync<T>(It.IsAny<ITurnContext>(), It.IsAny<CancellationToken>()))
|
||||
// .Returns(() => Task.FromResult(returns));
|
||||
// return mockRecognizer;
|
||||
//}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
|
||||
<AssemblyName>Microsoft.Bot.Builder.TestBot.Tests</AssemblyName>
|
||||
|
||||
<RootNamespace>Microsoft.BotBuilderSamples.Tests</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="appsettings.json" />
|
||||
<None Remove="xunit.runner.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="appsettings.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.1.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.1.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.1.1" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Builder.Testing\Microsoft.Bot.Builder.Testing.csproj" />
|
||||
<ProjectReference Include="..\Microsoft.Bot.Builder.TestBot\Microsoft.Bot.Builder.TestBot.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Properties\launchSettings.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<AdditionalFiles Include="stylecop.json" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"cognitiveModels": {
|
||||
"calendar": {
|
||||
"luisAppId": "Set the value here or in launchSettings.json for local dev",
|
||||
"luisEndpointKey": "Set the value here or in launchSettings.json for local dev",
|
||||
"luisEndpoint": "Set the value here or in launchSettings.json for local dev"
|
||||
},
|
||||
"toDo": {
|
||||
"luisAppId": "Set the value here or in launchSettings.json for local dev",
|
||||
"luisEndpointKey": "Set the value here or in launchSettings.json for local dev",
|
||||
"luisEndpoint": "Set the value here or in launchSettings.json for local dev"
|
||||
},
|
||||
"email": {
|
||||
"luisAppId": "Set the value here or in launchSettings.json for local dev",
|
||||
"luisEndpointKey": "Set the value here or in launchSettings.json for local dev",
|
||||
"luisEndpoint": "Set the value here or in launchSettings.json for local dev"
|
||||
},
|
||||
"flightBooking": {
|
||||
"luisAppId": "Set the value here or in launchSettings.json for local dev",
|
||||
"luisEndpointKey": "Set the value here or in launchSettings.json for local dev",
|
||||
"luisEndpoint": "Set the value here or in launchSettings.json for local dev"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"settings": {
|
||||
"namingRules": {
|
||||
"allowCommonHungarianPrefixes": true,
|
||||
"allowedHungarianPrefixes": [
|
||||
"lu"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -81,7 +81,7 @@ namespace Microsoft.BotBuilderSamples
|
|||
private async Task<DialogTurnResult> InvokeTaskStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
|
||||
{
|
||||
var luisResult = await _luisRecognizer.RecognizeAsync<FlightBooking>(stepContext.Context, cancellationToken);
|
||||
|
||||
|
||||
switch (luisResult.TopIntent().intent)
|
||||
{
|
||||
case FlightBooking.Intent.BookFlight:
|
||||
|
|
|
@ -113,6 +113,15 @@ namespace Microsoft.BotBuilderSamples
|
|||
});
|
||||
}
|
||||
|
||||
private static void RegisterDialogs(IServiceCollection services)
|
||||
{
|
||||
// Register booking dialog
|
||||
services.AddSingleton(new BookingDialog(new GetBookingDetailsDialog(), new FlightBookingService()));
|
||||
|
||||
// The Dialog that will be run by the bot.
|
||||
services.AddSingleton<MainDialog>();
|
||||
}
|
||||
|
||||
private void RegisterLuisRecognizers(IServiceCollection services)
|
||||
{
|
||||
var luisIsConfigured = !string.IsNullOrEmpty(Configuration["LuisAppId"]) && !string.IsNullOrEmpty(Configuration["LuisAPIKey"]) && !string.IsNullOrEmpty(Configuration["LuisAPIHostName"]);
|
||||
|
@ -127,14 +136,5 @@ namespace Microsoft.BotBuilderSamples
|
|||
services.AddSingleton<IRecognizer>(recognizer);
|
||||
}
|
||||
}
|
||||
|
||||
private static void RegisterDialogs(IServiceCollection services)
|
||||
{
|
||||
// Register booking dialog
|
||||
services.AddSingleton(new BookingDialog(new GetBookingDetailsDialog(), new FlightBookingService()));
|
||||
|
||||
// The Dialog that will be run by the bot.
|
||||
services.AddSingleton<MainDialog>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче