如何在Bot Framework的测试功能中访问用户和会话数据

在运行单元测试时,我需要访问用户和会话数据。

在我的机器人代码中,我已经按照MS documentation实施了用户和会话数据。

在为对话框运行单元测试时,我无法访问在测试期间更新的保存用户数据。

以下是我针对机器人测试代码的设置(来自Virtual Assistant模板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仓库。

lovedanjun 回答:如何在Bot Framework的测试功能中访问用户和会话数据

尝试在 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 保存。然后,您应该能够阅读您在以后的回合中保存的内容。

本文链接:https://www.f2er.com/3108510.html

大家都在问