如何在 Bot Framework 的测试函数中访问用户和对话数据
Posted
技术标签:
【中文标题】如何在 Bot Framework 的测试函数中访问用户和对话数据【英文标题】:How to Access User & Conversation Data in Test Functions for Bot Framework 【发布时间】:2020-03-09 11:45:19 【问题描述】:我需要在运行单元测试时访问用户和对话数据。
在我的机器人代码中,我在MS documentation 之后实现了用户和对话数据。
在为我的对话框运行单元测试时,我无法访问我在测试期间更新的保存用户数据。
下面是我的机器人测试代码设置(来自虚拟助手模板BotTestBase.cs
)。
var storage = new MemoryStorage();
Services.AddSingleton(new UserState(storage));
Services.AddSingleton(new ConversationState(storage));
Services.AddSingleton(sp =>
var userState = sp.GetService<UserState>();
var conversationState = sp.GetService<ConversationState>();
return new BotStateSet(userState, conversationState);
);
这是我的测试函数:
userState = new UserState(new MemoryStorage());
var subDialog = new SubDialog(userState);
var MainDialog = new MainDialog(subDialog);
var testClient = new DialogTestClient(Channels.Msteams, MainDialog);
// some code here
reply = await testClient.SendActivityAsync<IMessageActivity>("Yes");
Assert.AreEqual("XXXX", ((HeroCard)reply.Attachments[0].Content).Text);
reply = await testClient.SendActivityAsync<IMessageActivity>("No");
Assert.AreEqual("OOOO", ((HeroCard)reply.Attachments[0].Content).Text);
reply = await testClient.SendActivityAsync<IMessageActivity>("Checkout");
Assert.AreEqual("XOXO", ((HeroCard)reply.Attachments[0].Content).Text);
下面是我在 subDialog 中的用户数据。我可以通过userProfile.xxxx = oooo
更新数据:
var userStateProfileAccessors = _userState.CreateProperty<UserProfile>(nameof(UserProfile));
var userProfile = await userStateProfileAccessors.GetAsync(dc.Context, () => new UserProfile());
发送Yes
后对话框进入子对话框,发送No
后用户数据更新。
在我发送Checkout
之后,将访问用户数据以确定下一步。但是好像用户数据没有更新,我发现里面的所有属性都为空。
有人知道如何在 bot 框架中访问用户数据以进行单元测试吗?
更新
我创建了 MRE。我通过制作一个虚拟助手模板来做到这一点,然后我创建了一个对话框 CheckoutDialog.cs,它为我的 userProfile.DiscountStatus 分配一个值,并在下一步中检查它。我为此对话框 CheckoutTests.cs 创建了一个测试,当我调试测试时,我可以看到我的 userProfile.DiscountStatus 不会在步骤之间保持其状态。 Here 是 git 仓库。
【问题讨论】:
如果你能分享minimal reproducible example,那就太棒了。目前没有足够的信息来重现这里的问题。 由于缺乏足够的信息来直接提供适当的帮助,我建议的最好方法是查看这里的文档How to unit test bots 我正在研究最小的可重现示例。稍后分享,谢谢。 这能回答你的问题吗? ***.com/a/43244859/12217161 @MasLoo 它不起作用。我猜 DialogtestBase 与 V3 一起使用。我的机器人是用 V4 开发的。 【参考方案1】:尝试在var testClient = new DialogTestClient(Channels.Msteams, MainDialog);
上方添加以下行
AutoSaveStateMiddleware autoSaveStateMiddleware = new AutoSaveStateMiddleware(userState);
然后将该行更改为:
var testClient = new DialogTestClient(Channels.Msteams, MainDialog, middlewares: new List<IMiddleware>() autoSaveStateMiddleware );
我创建了一个包含 2 个项目和 3 个类的简单存储库来测试这一点: Repo with unit test of a dialog which saves & retrieves user state between 2 turns
查看DialogTestClient.cs from Microsoft.Bot.Builder.Testing中的DialogTestClient.cs(第39行)代码,客户端仅在ConversationState上实现AutoSaveStateMiddleware。
public DialogTestClient(string channelId, Dialog targetDialog, object initialDialogOptions = null, IEnumerable<IMiddleware> middlewares = null, ConversationState conversationState = null)
ConversationState = conversationState ?? new ConversationState(new MemoryStorage());
_testAdapter = new TestAdapter(channelId)
.Use(new AutoSaveStateMiddleware(ConversationState));
AddUserMiddlewares(middlewares);
var dialogState = ConversationState.CreateProperty<DialogState>("DialogState");
_callback = GetDefaultCallback(targetDialog, initialDialogOptions, dialogState);
在您的情况下,您只运行对话框。根据我所见,将状态在线保存到存储提供程序通常是在 Bot.OnTurnAsync 方法中完成的。在这种情况下,您没有机器人。使用提供的 IMiddleware 参数在 UserState 上添加 AutoSaveStateMiddleware 将导致 UserState 保存。然后您应该能够在以后的回合中读取您保存的内容。
【讨论】:
您好,感谢您的回答。这个对我有用。只是有另一个问题,我正在使用“UserProfile”,就像你在回购中所做的那样。 var userStateAccessors = _userState.CreateProperty以上是关于如何在 Bot Framework 的测试函数中访问用户和对话数据的主要内容,如果未能解决你的问题,请参考以下文章
Microsoft Bot Framework - 如何将数据从 Azure 数据库获取到我的 Bot 项目?
如何在 Bot Framework C# 中使用 Bing Speech API