我已经创建了一个希望被转发到
using Microsoft.Bot.Builder.Dialogs;
using pc.apm.bot.Services;
using System;
using System.Diagnostics;
using System.Threading.Tasks;
namespace pc.apm.bot.Dialogs
{
[Serializable]
public class NewUserDialog : IDialog<string>
{
IApmService _apmService;
LangaugeCodes _langaugeCode;
public NewUserDialog(IApmService apmService, LangaugeCodes langaugeCode)
{
_apmService = apmService;
_langaugeCode = langaugeCode;
}
public async Task StartAsync(IDialogContext context)
{
if (new TraceSwitch("apmDiagnostics", "").Level == TraceLevel.Info)
await context.PostAsync($"Current Dialog: {this.GetType().Name}");
context.Wait<string>(MessageReceivedAsync);
}
private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<string> result)
{
var userEmail = await result;
await context.PostAsync(StringResourceService.GetStringResource(StringKeys.NewUserStarted_Key, _langaugeCode));
var apmId = await _apmService.CreateUserAsync(userEmail.ToLower());
var UserProvisionedAlfabet_Text = StringResourceService.GetStringResource(StringKeys.UserProvisionedAlfabet_Key, _langaugeCode);
await context.PostAsync(String.Format(UserProvisionedAlfabet_Text, userEmail));
context.Done(apmId);
}
}
}
现在它的工作方式是在前面的对话框上,我有一些逻辑决定需要为一个新用户提供服务,如果是这样的话,它就会将用户的电子邮件转发给NewUserDialog。
await context.Forward(
child: new NewUserDialog(),
resume: (c, r) => AddProfile(context, result),
item: user.Email,
token: CancellationToken.None);
因此,所有的工作都很好,而且很好,我遇到的问题是单元测试代码;我正在尝试遵循bot构建器测试项目中列出的内容
https://github.com/Microsoft/BotBuilder/tree/master/CSharp/Tests/Microsoft.Bot.Sample.Tests
现在我的测试开始了,就在我的NewUserDialog试图等待电子邮件地址失败和异常被抛出的时候
pc.apm.bot.tests.Test_New_User_Dialog.Create_New_User抛出异常: Microsoft.Bot.Builder.Internals.Fibers.InvalidTypeException:无效类型:预期的System.String,有活动
因此,我发现这是一个类型问题;但是我不知道如何通过测试代码将电子邮件地址传递给对话框。
这是我的测试代码
using Autofac;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Builder.Dialogs.Internals;
using Microsoft.Bot.Builder.Tests;
using Microsoft.Bot.Connector;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using pc.apm.bot.Dialogs;
using pc.apm.bot.Services;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace pc.apm.bot.tests
{
[TestClass]
public class Test_New_User_Dialog : DialogTestBase
{
[TestMethod]
public async Task Test_method() => Assert.IsTrue(await Task.FromResult(true));
[TestMethod]
public async Task Create_New_User()
{
var mockApmService = new Mock<IApmService>(MockBehavior.Strict);
mockApmService
.Setup(m => m.CreateUserAsync(It.IsAny<string>()))
.Returns<string>(x => Task.FromResult("123-123"));
var NewUserDialog = new NewUserDialog(mockApmService.Object, LangaugeCodes.en_US);
var toBot = DialogTestBase.MakeTestMessage();
toBot.From.Id = Guid.NewGuid().ToString();
Func<IDialog<string>> MakeRoot = () => NewUserDialog;
using (new FiberTestBase.ResolveMoqAssembly(NewUserDialog))
using (var container = Build(Options.MockConnectorFactory | Options.ScopedQueue, NewUserDialog))
{
using (var scope = DialogModule.BeginLifetimeScope(container, toBot))
{
DialogModule_MakeRoot.Register(scope, MakeRoot);
await Conversation.SendAsync(scope, toBot);
var firstResponse = scope.Resolve<Queue<IMessageActivity>>().Dequeue();
Assert.IsTrue(firstResponse.Text.Equals("Looks as if you are a new user, let's get you started!"));
var secondResponse = scope.Resolve<Queue<IMessageActivity>>().Dequeue();
Assert.IsTrue(secondResponse.Text.Equals("A user for pawel.chooch@fake.com has been provisioned in System"));
}
}
}
}
}
因此,简单地说,我的问题是,如何通过从父对话框转发参数来测试接收参数的对话框?
发布于 2017-10-13 09:49:57
好吧,经过大量的努力,我终于得到了它,
using Autofac;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Builder.Dialogs.Internals;
using Microsoft.Bot.Builder.Tests;
using Microsoft.Bot.Connector;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using pc.apm.bot.Dialogs;
using pc.apm.bot.Services;
using pc.apm.bot.tests.Interfaces;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace pc.apm.bot.tests
{
[TestClass]
public class Test_New_User_Dialog : DialogTestBase
{
[TestMethod]
public async Task Test_method() => Assert.IsTrue(await Task.FromResult(true));
[TestMethod]
public async Task Create_New_user_Dialog()
{
var mockRootDialog = new Mock<IMessageRecievedDialog<IMessageActivity>>(MockBehavior.Loose);
var mockApmService = new Mock<IApmService>(MockBehavior.Strict);
mockApmService.Setup(m => m.CreateUserAsync(It.IsAny<string>()))
.Returns<string>(x => Task.FromResult("123-123"));
var NewUserDialog = new NewUserDialog(mockApmService.Object, LangaugeCodes.en_US);
var userEmail = "pawel.chooch@fake.com";
mockRootDialog.Setup(d => d.StartAsync(It.IsAny<IDialogContext>()))
.Returns<IDialogContext>(
context =>
{
context.Wait(mockRootDialog.Object.MessageRecievedAsync);
return Task.CompletedTask;
});
mockRootDialog.Setup(d => d.MessageRecievedAsync(It.IsAny<IDialogContext>(), It.IsAny<IAwaitable<IMessageActivity>>()))
.Returns<IDialogContext, IAwaitable<IMessageActivity>>(async (context, message) =>
{
var email = await message;
await context.Forward(
child: NewUserDialog,
resume: async (c, r) =>
{
Assert.AreEqual("123-123", await r);
c.Done<object>(null);
},
item: email.Text,
token: CancellationToken.None);
});
var toBot = DialogTestBase.MakeTestMessage();
using (new FiberTestBase.ResolveMoqAssembly(mockRootDialog.Object, NewUserDialog))
using (var container = Build(Options.MockConnectorFactory | Options.ScopedQueue, mockRootDialog.Object, NewUserDialog))
using (var scope = DialogModule.BeginLifetimeScope(container, toBot))
{
DialogModule_MakeRoot.Register(scope, () => mockRootDialog.Object);
var task = scope.Resolve<IPostToBot>();
toBot.Text = userEmail;
await task.PostAsync(toBot, CancellationToken.None);
var firstResponse = scope.Resolve<Queue<IMessageActivity>>().Dequeue();
Assert.IsTrue(firstResponse.Text.Equals("Looks as if you are a new user, let's get you started!"));
var secondResponse = scope.Resolve<Queue<IMessageActivity>>().Dequeue();
Assert.IsTrue(secondResponse.Text.Equals($"A user for {userEmail} has been provisioned in ALFABET"));
}
}
}
}
现在撇开apm服务不说,我创建了一个接口IMessageRecievedDialog。
using Microsoft.Bot.Builder.Dialogs;
using System.Threading.Tasks;
namespace pc.apm.bot.tests.Interfaces
{
public interface IMessageRecievedDialog<T> : IDialog<T>
{
Task MessageRecievedAsync(IDialogContext context, IAwaitable<T> result);
}
}
实际上,这在Microsoft.Bot.Builder.Tests名称空间中并不是必需的,因为有一个接口"IDialogFrames“,这是完全相同的事情。我从DialogTask_Forward测试中再次从Microsoft.bot.builder.tests中获得了解决方案的灵感。
[TestMethod]
public async Task DialogTask_Forward()
{
var dialogOne = new Mock<IDialogFrames<string>>(MockBehavior.Loose);
var dialogTwo = new Mock<IDialogFrames<string>>(MockBehavior.Loose);
const string testMessage = "foo";
dialogOne
.Setup(d => d.StartAsync(It.IsAny<IDialogContext>()))
.Returns<IDialogContext>(async context => { context.Wait(dialogOne.Object.ItemReceived); });
dialogOne
.Setup(d => d.ItemReceived(It.IsAny<IDialogContext>(), It.IsAny<IAwaitable<IMessageActivity>>()))
.Returns<IDialogContext, IAwaitable<IMessageActivity>>(async (context, message) =>
{
var msg = await message;
await context.Forward(dialogTwo.Object, dialogOne.Object.ItemReceived<string>, msg, CancellationToken.None);
});
dialogOne
.Setup(d => d.ItemReceived(It.IsAny<IDialogContext>(), It.IsAny<IAwaitable<string>>()))
.Returns<IDialogContext, IAwaitable<string>>(async (context, message) =>
{
var msg = await message;
Assert.AreEqual(testMessage, msg);
context.Wait(dialogOne.Object.ItemReceived);
});
dialogTwo
.Setup(d => d.StartAsync(It.IsAny<IDialogContext>()))
.Returns<IDialogContext>(async context => { context.Wait(dialogTwo.Object.ItemReceived); });
dialogTwo
.Setup(d => d.ItemReceived(It.IsAny<IDialogContext>(), It.IsAny<IAwaitable<IMessageActivity>>()))
.Returns<IDialogContext, IAwaitable<IMessageActivity>>(async (context, message) =>
{
var msg = await message;
context.Done(msg.Text);
});
Func<IDialog<object>> MakeRoot = () => dialogOne.Object;
var toBot = MakeTestMessage();
using (new FiberTestBase.ResolveMoqAssembly(dialogOne.Object, dialogTwo.Object))
using (var container = Build(Options.None, dialogOne.Object, dialogTwo.Object))
{
using (var scope = DialogModule.BeginLifetimeScope(container, toBot))
{
DialogModule_MakeRoot.Register(scope, MakeRoot);
var task = scope.Resolve<IPostToBot>();
toBot.Text = testMessage;
await task.PostAsync(toBot, CancellationToken.None);
dialogOne.Verify(d => d.StartAsync(It.IsAny<IDialogContext>()), Times.Once);
dialogOne.Verify(d => d.ItemReceived(It.IsAny<IDialogContext>(), It.IsAny<IAwaitable<IMessageActivity>>()), Times.Once);
dialogOne.Verify(d => d.ItemReceived(It.IsAny<IDialogContext>(), It.IsAny<IAwaitable<string>>()), Times.Once);
dialogTwo.Verify(d => d.StartAsync(It.IsAny<IDialogContext>()), Times.Once);
dialogTwo.Verify(d => d.ItemReceived(It.IsAny<IDialogContext>(), It.IsAny<IAwaitable<IMessageActivity>>()), Times.Once);
}
}
}
下面的链接确实帮助了https://channel9.msdn.com/Series/DevOps-for-the-Bot-Framework/Testing-the-Bot-Framework?term=bot
我仍然不太熟悉僵尸框架的特定代码,无法真正提供解释,因此我只是理所当然地认为它是理所当然的。不管怎样,我希望我的腿能帮到别人。干杯。
https://stackoverflow.com/questions/46671429
复制相似问题