You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Moq模拟Bot SDK ContinueConversationAsync抛出Unsupported expression异常

报错根因

System.ArgumentException : Unsupported expression: (TestAdapter)bot 是Moq抛出的,原因是你在Setup表达式里写了强制类型转换(TestAdapter)bot,Moq无法解析这种包含运行时类型转换的Lambda表达式,自然无法完成Mock配置。
另外你之前的Setup还有一个隐蔽错误:你配置的ContinueConversationAsync重载第二个参数是Activity类型,但你控制器里实际调用的重载第二个参数是ConversationReference类型,就算类型转换的问题解决了,Mock逻辑也不会命中。

解决方案

方案1:直接Mock基类方法(推荐,符合单元测试隔离依赖的要求)

你控制器里本身是把注入的_adapter强转为BotAdapter基类后调用方法,所以直接针对BotAdapter的对应方法重载做Mock即可,完全不需要转成TestAdapter。

  1. 先确认你测试类里_adapter的声明类型改成Mock<BotAdapter>(如果之前声明的是其他派生类,统一改成Mock基类即可,因为你调用的方法是基类定义的虚方法)
  2. 替换原来错误的Setup代码,保证参数类型和你实际调用的方法签名完全一致:
_adapter
    .Setup(a => a.ContinueConversationAsync(
        It.IsAny<string>(),
        It.IsAny<ConversationReference>(),
        It.IsAny<BotCallbackHandler>(),
        It.IsAny<CancellationToken>()))
    .Returns(Task.CompletedTask)
    .Verifiable();

调整后完整测试代码:

[Fact]
public async Task PostTeams_ReturnsAViewResult_ContainingTheMessageSent()
{
    // Arrange
    _microsoftGraphService
        .Setup(mock => mock.GetGraphUserDetails(It.IsAny<List<string>>(), It.IsAny<List<string>>()))
        .ReturnsAsync(GetUserDetails());
    _cosmosDBService
        .Setup(repo => repo.GetItemAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
        .ReturnsAsync(GetConversationReference());
    // 修正后的适配器Mock
    _adapter
        .Setup(a => a.ContinueConversationAsync(
            It.IsAny<string>(),
            It.IsAny<ConversationReference>(),
            It.IsAny<BotCallbackHandler>(),
            It.IsAny<CancellationToken>()))
        .Returns(Task.CompletedTask)
        .Verifiable();

    NotifyController controller = new NotifyController(
        _adapter.Object, 
        _configuration, 
        _cosmosDBService.Object, 
        _microsoftGraphService.Object, 
        _environment.Object, 
        _sendGridEmailService.Object, 
        _teamsChannelService.Object)
    {
        ControllerContext = _controllerContext
    };

    // Act
    var result = await controller.PostTeams(_proactiveMessageModel);

    // Assert
    var contentResult = Assert.IsType<ContentResult>(result);
    Assert.Contains("Test message", contentResult.Content);
    // 验证主动消息调用确实触发
    _adapter.Verify();
}

方案2:直接使用TestAdapter实例,无需Mock

如果不需要完全隔离适配器逻辑,直接实例化Bot SDK自带的TestAdapter传入控制器即可,不需要用Moq包装。TestAdapter本身已经实现了ContinueConversationAsync的测试逻辑,会直接执行你传入的Bot回调,你还可以额外断言回调里发送的消息内容是否符合预期,更贴近真实运行场景:

// 不需要Mock<BotAdapter>,直接实例化测试适配器
var testAdapter = new TestAdapter();
// 构造控制器的时候直接传入testAdapter实例即可
var controller = new NotifyController(
    testAdapter, 
    // 其他参数保持不变
    ...
);

内容的提问来源于stack exchange,提问作者dickiebow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 12:12:21