如何使用React Testing Library为Cytoscape编写集成测试?
为Cytoscape编写React集成测试的可行方法
1. Mock Cytoscape库,测试组件交互逻辑
直接测试Canvas渲染的视觉效果难度高,可通过Mock Cytoscape核心库,聚焦测试组件如何调用Cytoscape的API(如节点添加、布局执行等),验证逻辑正确性。
// 测试文件中Mock cytoscape jest.mock('cytoscape', () => { const mockInstance = { add: jest.fn(), layout: jest.fn(() => ({ run: jest.fn() })), nodes: jest.fn(() => ({ length: 2 })), edges: jest.fn(() => ({ length: 1 })) }; const mockCytoscape = jest.fn(() => mockInstance); mockCytoscape.use = jest.fn(); return mockCytoscape; }); // 测试组件初始化逻辑 import { render, screen } from '@testing-library/react'; import CytoscapeGraph from './CytoscapeGraph'; import cytoscape from 'cytoscape'; test('初始化时正确创建实例并添加节点边', () => { const testData = { nodes: [{ data: { id: 'n1' } }, { data: { id: 'n2' } }], edges: [{ data: { source: 'n1', target: 'n2' } }] }; render(<CytoscapeGraph graphData={testData} />); expect(cytoscape).toHaveBeenCalled(); const mockCy = cytoscape.mock.results[0].value; expect(mockCy.add).toHaveBeenCalledWith([...testData.nodes, ...testData.edges]); expect(mockCy.layout().run).toHaveBeenCalled(); });
2. 测试DOM交互触发的Cytoscape行为
模拟用户操作(如点击按钮添加节点),验证组件是否正确调用Cytoscape的对应API。
test('点击添加节点按钮后,实例添加新节点', () => { render(<CytoscapeGraph />); const mockCy = cytoscape.mock.results[0].value; screen.getByRole('button', { name: /添加节点/i }).click(); expect(mockCy.add).toHaveBeenCalledWith(expect.arrayContaining([ expect.objectContaining({ data: expect.objectContaining({ id: expect.any(String) }) }) ])); });
3. 直接使用Cytoscape API断言内部状态
在jsdom环境下,无需渲染Canvas即可初始化Cytoscape实例,直接调用API验证节点数量、选中状态等内部逻辑。
test('节点边数量与传入数据一致', () => { const testData = { nodes: [{ data: { id: 'n1' } }, { data: { id: 'n2' } }], edges: [{ data: { source: 'n1', target: 'n2' } }] }; render(<CytoscapeGraph graphData={testData} />); const container = screen.getByTestId('cytoscape-container'); // 直接初始化实例(若组件用ref管理,也可通过组件ref获取) const cy = cytoscape({ container, elements: [...testData.nodes, ...testData.edges] }); expect(cy.nodes().length).toBe(2); expect(cy.edges().length).toBe(1); // 测试节点选中逻辑 cy.nodes('#n1').select(); expect(cy.nodes(':selected').length).toBe(1); });
4. 测试自定义事件回调
验证Cytoscape内部事件(如节点点击)是否正确传递给组件的回调函数。
test('节点点击触发组件的onNodeClick回调', () => { const mockOnNodeClick = jest.fn(); render(<CytoscapeGraph onNodeClick={mockOnNodeClick} />); const mockCy = cytoscape.mock.results[0].value; // 模拟Cytoscape触发节点点击事件 mockCy.nodes = jest.fn(() => ({ on: jest.fn((_, handler) => { handler({ target: { data: () => ({ id: 'n1' }) } }); }) })); // 重新渲染触发组件内的事件绑定逻辑 render(<CytoscapeGraph onNodeClick={mockOnNodeClick} />); expect(mockOnNodeClick).toHaveBeenCalledWith(expect.objectContaining({ id: 'n1' })); });
注意事项
- 遵循React-testing-library的理念:优先测试用户可见的行为,而非内部实现细节。
- 视觉渲染验证需交给端到端测试(如Cypress),集成测试聚焦业务逻辑与API调用正确性。
- 若组件通过ref管理Cytoscape实例,可利用
render的container参数或screen.getByTestId结合ref获取实例。
内容的提问来源于stack exchange,提问作者sai vineeth
相关产品推荐
相关产品推荐

