# 创建模拟对象来使层抽象化

Copilot Chat 有助于创建可用于单元测试的模拟对象。

创建单元测试时，请务必确保其相互隔离，不依赖于外部服务。 实现这一目标的一种方法是创建模拟对象，以抽象化应用程序的各个层。
Copilot Chat 可帮助你生成创建这些模拟对象所需的代码。

## 示例方案

假设有一个使用 TypeScript 构建的网站，它显示运行程序列表。 你有一种从数据库提取运行程序的服务，以及使用此服务的服务器端代码。 你想要测试服务器端代码，但不想调用数据库。 可以请求 Copilot Chat 为服务生成模拟对象。

```typescript id=mock-service
// SvelteKit example at +page.server.ts
import service from './service';

export async function load({ params }) {
  const runner = await service.getRunner(params.id);

  return {
    runner
  };
}
```

## 示例提示

此示例假定你使用 [vitest](https://vitest.dev/) 进行测试，但也可使用其他测试运行程序。

```copilot copy prompt ref=mock-service
/tests Create a unit test to ensure the service is called correctly. Mock the service object.
```

如果你有要 Copilot 用作模型的现有测试，则可以用于 `#file: path/to/test-file.js` 提供文件的路径，并在提示中包含此信息。

## 示例响应

> \[!NOTE] 以下响应是示例。 Copilot Chat 的回答是不确定的，因此你可能会得到与这里所显示的不同的回答。

Copilot 提供它将实现的计划以及包含模拟的代码文本。

```typescript
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { load } from './+page.server.ts';

// Mock the entire service module
vi.mock('./service', () => ({
  default: {
    getRunner: vi.fn()
  }
}));

// Import the mocked service
import service from './service';

describe('load function', () => {
  const mockRunner = {
    id: '123',
    name: 'Test Runner',
    status: 'active'
  };

  beforeEach(() => {
    // Reset mock before each test
    vi.resetAllMocks();

    // Setup default mock implementation
    (service.getRunner as any).mockResolvedValue(mockRunner);
  });

  it('should fetch runner with correct id', async () => {
    const params = { id: '123' };
    const result = await load({ params });

    expect(service.getRunner).toHaveBeenCalledWith('123');
    expect(service.getRunner).toHaveBeenCalledTimes(1);
    expect(result).toEqual({ runner: mockRunner });
  });
});
```

## 延伸阅读

* [GitHub Copilot 对话助手的提示设计](/zh/copilot/concepts/prompting/prompt-engineering)
* [使用 GitHub Copilot 的最佳做法](/zh/copilot/get-started/best-practices)