TypeScript开发Teams Bot/消息扩展应用单元测试求助
测试无对话框的Teams Bot/Message Extension功能(TypeScript)
针对你未使用对话框的Teams Bot/Message Extension,下面是直接测试onMessageActivity和handleTeamsMessagingExtensionFetchTask的具体方案,基于Jest测试框架(TypeScript环境)。
前期准备
先安装必要的测试依赖:
npm install --save-dev jest ts-jest @types/jest botbuilder-core botbuilder-testing
在jest.config.js中配置TypeScript支持:
module.exports = { preset: 'ts-jest', testEnvironment: 'node', roots: ['<rootDir>/tests'], transform: { '^.+\\.tsx?$': 'ts-jest' } };
测试onMessageActivity
onMessageActivity接收TurnContext参数,核心是构造包含消息活动的上下文,直接调用方法并验证输出。
示例测试代码
import { TurnContext, ActivityTypes, TestAdapter } from 'botbuilder'; import { MyTeamsBot } from '../src/bot'; describe('MyTeamsBot - onMessageActivity', () => { let bot: MyTeamsBot; let adapter: TestAdapter; beforeEach(() => { bot = new MyTeamsBot(); adapter = new TestAdapter(); }); it('回复问候消息', async () => { const testMessage = { type: ActivityTypes.Message, text: 'Hello', from: { id: 'test-user' }, recipient: { id: 'test-bot' }, conversation: { id: 'test-conv' } }; const context = new TurnContext(adapter, testMessage); await bot.onMessageActivity(context); const replies = await adapter.getReplies(); expect(replies.length).toBe(1); expect(replies[0].text).toBe('Hi there! How can I assist you?'); }); it('处理特定指令', async () => { const testMessage = { type: ActivityTypes.Message, text: 'get status', from: { id: 'test-user' }, recipient: { id: 'test-bot' }, conversation: { id: 'test-conv' } }; const context = new TurnContext(adapter, testMessage); await bot.onMessageActivity(context); const replies = await adapter.getReplies(); expect(replies[0].text).toContain('Current status: active'); }); });
测试handleTeamsMessagingExtensionFetchTask
这个方法处理Message Extension的composeExtension/fetchTask调用,需要构造类型为invoke的活动,指定正确的name字段,然后验证返回的MessagingExtensionResult。
示例测试代码
import { TurnContext, ActivityTypes, MessagingExtensionResult } from 'botbuilder'; import { MyTeamsBot } from '../src/bot'; describe('MyTeamsBot - handleTeamsMessagingExtensionFetchTask', () => { let bot: MyTeamsBot; let adapter: TestAdapter; beforeEach(() => { bot = new MyTeamsBot(); adapter = new TestAdapter(); }); it('返回包含自适应卡片的任务模块', async () => { const invokeActivity = { type: ActivityTypes.Invoke, name: 'composeExtension/fetchTask', from: { id: 'test-user' }, recipient: { id: 'test-bot' }, conversation: { id: 'test-conv' }, value: { commandId: 'fetchTaskCommand' } }; const context = new TurnContext(adapter, invokeActivity); const result = await bot.handleTeamsMessagingExtensionFetchTask(context); expect(result).toBeInstanceOf(MessagingExtensionResult); expect(result.task).toBeDefined(); expect(result.task?.type).toBe('adaptiveCard'); expect(result.task?.value).toHaveProperty('type', 'AdaptiveCard'); expect(result.task?.value.body).toBeInstanceOf(Array); }); it('处理缺少commandId的情况', async () => { const invalidInvokeActivity = { type: ActivityTypes.Invoke, name: 'composeExtension/fetchTask', from: { id: 'test-user' }, recipient: { id: 'test-bot' }, conversation: { id: 'test-conv' }, value: {} }; const context = new TurnContext(adapter, invalidInvokeActivity); const result = await bot.handleTeamsMessagingExtensionFetchTask(context); expect(result.task?.value.body).toContain('Invalid command'); }); });
关键注意事项
- 模拟外部依赖:如果Bot调用了数据库、API等外部服务,用
jest.mock替换这些模块,避免真实调用影响测试:jest.mock('../src/services/statusService', () => ({ getCurrentStatus: jest.fn().mockResolvedValue('active') })); - 错误场景覆盖:测试无效输入、异常情况(比如服务调用失败),确保Bot能正确处理或返回友好提示。
- 类型安全:利用TypeScript的类型检查,确保构造的Activity、参数符合Bot Framework的类型定义,避免类型错误。
- TestAdapter的使用:
TestAdapter会自动捕获Bot发送的回复,无需手动模拟context.sendActivity方法,简化测试逻辑。
内容的提问来源于stack exchange,提问作者XDeveloper
相关产品推荐
相关产品推荐

