@creatoria/miniapp-mcp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +469 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +144 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/defaults.d.ts +73 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +118 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/loader.d.ts +50 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +189 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/core/element-ref.d.ts +44 -0
- package/dist/core/element-ref.d.ts.map +1 -0
- package/dist/core/element-ref.js +213 -0
- package/dist/core/element-ref.js.map +1 -0
- package/dist/core/logger.d.ts +55 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +378 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/output.d.ts +21 -0
- package/dist/core/output.d.ts.map +1 -0
- package/dist/core/output.js +56 -0
- package/dist/core/output.js.map +1 -0
- package/dist/core/report-generator.d.ts +24 -0
- package/dist/core/report-generator.d.ts.map +1 -0
- package/dist/core/report-generator.js +212 -0
- package/dist/core/report-generator.js.map +1 -0
- package/dist/core/session.d.ts +83 -0
- package/dist/core/session.d.ts.map +1 -0
- package/dist/core/session.js +306 -0
- package/dist/core/session.js.map +1 -0
- package/dist/core/timeout.d.ts +49 -0
- package/dist/core/timeout.d.ts.map +1 -0
- package/dist/core/timeout.js +67 -0
- package/dist/core/timeout.js.map +1 -0
- package/dist/core/tool-logger.d.ts +83 -0
- package/dist/core/tool-logger.d.ts.map +1 -0
- package/dist/core/tool-logger.js +453 -0
- package/dist/core/tool-logger.js.map +1 -0
- package/dist/core/validation.d.ts +39 -0
- package/dist/core/validation.d.ts.map +1 -0
- package/dist/core/validation.js +93 -0
- package/dist/core/validation.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +7 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +85 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/assert.d.ts +108 -0
- package/dist/tools/assert.d.ts.map +1 -0
- package/dist/tools/assert.js +291 -0
- package/dist/tools/assert.js.map +1 -0
- package/dist/tools/automator.d.ts +45 -0
- package/dist/tools/automator.d.ts.map +1 -0
- package/dist/tools/automator.js +186 -0
- package/dist/tools/automator.js.map +1 -0
- package/dist/tools/element.d.ts +253 -0
- package/dist/tools/element.d.ts.map +1 -0
- package/dist/tools/element.js +615 -0
- package/dist/tools/element.js.map +1 -0
- package/dist/tools/index.d.ts +97 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +1565 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/miniprogram.d.ts +79 -0
- package/dist/tools/miniprogram.d.ts.map +1 -0
- package/dist/tools/miniprogram.js +245 -0
- package/dist/tools/miniprogram.js.map +1 -0
- package/dist/tools/network.d.ts +65 -0
- package/dist/tools/network.d.ts.map +1 -0
- package/dist/tools/network.js +205 -0
- package/dist/tools/network.js.map +1 -0
- package/dist/tools/page.d.ts +108 -0
- package/dist/tools/page.d.ts.map +1 -0
- package/dist/tools/page.js +307 -0
- package/dist/tools/page.js.map +1 -0
- package/dist/tools/record.d.ts +86 -0
- package/dist/tools/record.d.ts.map +1 -0
- package/dist/tools/record.js +316 -0
- package/dist/tools/record.js.map +1 -0
- package/dist/tools/snapshot.d.ts +82 -0
- package/dist/tools/snapshot.d.ts.map +1 -0
- package/dist/tools/snapshot.js +258 -0
- package/dist/tools/snapshot.js.map +1 -0
- package/dist/types.d.ts +240 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/docs/SIMPLE_USAGE.md +210 -0
- package/docs/api/README.md +244 -0
- package/docs/api/assert.md +1015 -0
- package/docs/api/automator.md +345 -0
- package/docs/api/element.md +1454 -0
- package/docs/api/miniprogram.md +558 -0
- package/docs/api/network.md +883 -0
- package/docs/api/page.md +909 -0
- package/docs/api/record.md +963 -0
- package/docs/api/snapshot.md +792 -0
- package/docs/architecture.E-Docs.md +1359 -0
- package/docs/architecture.F1.md +720 -0
- package/docs/architecture.F2.md +871 -0
- package/docs/architecture.F3.md +905 -0
- package/docs/architecture.md +90 -0
- package/docs/charter.A1.align.yaml +170 -0
- package/docs/charter.A2.align.yaml +199 -0
- package/docs/charter.A3.align.yaml +242 -0
- package/docs/charter.A4.align.yaml +227 -0
- package/docs/charter.B1.align.yaml +179 -0
- package/docs/charter.B2.align.yaml +200 -0
- package/docs/charter.B3.align.yaml +200 -0
- package/docs/charter.B4.align.yaml +188 -0
- package/docs/charter.C1.align.yaml +190 -0
- package/docs/charter.C2.align.yaml +202 -0
- package/docs/charter.C3.align.yaml +211 -0
- package/docs/charter.C4.align.yaml +263 -0
- package/docs/charter.C5.align.yaml +220 -0
- package/docs/charter.D1.align.yaml +190 -0
- package/docs/charter.D2.align.yaml +234 -0
- package/docs/charter.D3.align.yaml +206 -0
- package/docs/charter.E-Docs.align.yaml +294 -0
- package/docs/charter.F1.align.yaml +193 -0
- package/docs/charter.F2.align.yaml +248 -0
- package/docs/charter.F3.align.yaml +287 -0
- package/docs/charter.G.align.yaml +174 -0
- package/docs/charter.align.yaml +111 -0
- package/docs/examples/session-report-usage.md +449 -0
- package/docs/maintenance.md +682 -0
- package/docs/playwright-mcp/350/260/203/347/240/224.md +53 -0
- package/docs/setup-guide.md +775 -0
- package/docs/tasks.A1.atomize.md +296 -0
- package/docs/tasks.A2.atomize.md +408 -0
- package/docs/tasks.A3.atomize.md +564 -0
- package/docs/tasks.A4.atomize.md +496 -0
- package/docs/tasks.B1.atomize.md +352 -0
- package/docs/tasks.B2.atomize.md +561 -0
- package/docs/tasks.B3.atomize.md +508 -0
- package/docs/tasks.B4.atomize.md +504 -0
- package/docs/tasks.C1.atomize.md +540 -0
- package/docs/tasks.C2.atomize.md +665 -0
- package/docs/tasks.C3.atomize.md +745 -0
- package/docs/tasks.C4.atomize.md +908 -0
- package/docs/tasks.C5.atomize.md +755 -0
- package/docs/tasks.D1.atomize.md +547 -0
- package/docs/tasks.D2.atomize.md +619 -0
- package/docs/tasks.D3.atomize.md +790 -0
- package/docs/tasks.E-Docs.atomize.md +1204 -0
- package/docs/tasks.atomize.md +189 -0
- package/docs/troubleshooting.md +855 -0
- package/docs//345/256/214/346/225/264/345/256/236/347/216/260/346/226/271/346/241/210.md +155 -0
- package/docs//345/274/200/345/217/221/344/273/273/345/212/241/350/256/241/345/210/222.md +110 -0
- package/docs//345/276/256/344/277/241/345/260/217/347/250/213/345/272/217/350/207/252/345/212/250/345/214/226API/345/256/214/346/225/264/346/226/207/346/241/243.md +894 -0
- package/docs//345/276/256/344/277/241/345/260/217/347/250/213/345/272/217/350/207/252/345/212/250/345/214/226/345/256/214/346/225/264/346/223/215/344/275/234/346/211/213/345/206/214.md +1885 -0
- package/docs//346/216/245/345/217/243/346/226/271/346/241/210.md +565 -0
- package/docs//347/254/254/344/270/200/347/211/210/346/234/254/346/226/271/346/241/210.md +380 -0
- package/package.json +87 -0
|
@@ -0,0 +1,883 @@
|
|
|
1
|
+
# Network API
|
|
2
|
+
|
|
3
|
+
> Network 工具提供网络请求和微信 API 的模拟(Mock)功能,用于离线测试和错误场景模拟。
|
|
4
|
+
|
|
5
|
+
## 工具列表
|
|
6
|
+
|
|
7
|
+
| 工具名称 | 描述 | 主要用途 |
|
|
8
|
+
|---------|------|----------|
|
|
9
|
+
| `network_mock_wx_method` | 模拟任意微信 API | 通用 API 模拟 |
|
|
10
|
+
| `network_restore_wx_method` | 恢复被模拟的微信 API | 清除单个模拟 |
|
|
11
|
+
| `network_mock_request` | 模拟 wx.request 成功响应 | 网络请求成功场景 |
|
|
12
|
+
| `network_mock_request_failure` | 模拟 wx.request 失败 | 网络请求错误处理 |
|
|
13
|
+
| `network_restore_request` | 恢复 wx.request 原始行为 | 清除请求模拟 |
|
|
14
|
+
| `network_restore_all_mocks` | 恢复所有被模拟的 API | 批量清除模拟 |
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## network_mock_wx_method
|
|
19
|
+
|
|
20
|
+
模拟任意微信 API 方法(`wx.*`),使其返回指定的结果或错误。
|
|
21
|
+
|
|
22
|
+
### 参数
|
|
23
|
+
|
|
24
|
+
| 参数名 | 类型 | 必需 | 默认值 | 描述 |
|
|
25
|
+
|--------|------|------|--------|------|
|
|
26
|
+
| `method` | string | ✅ | - | 微信 API 方法名(如 `getSystemInfo`, `showToast`) |
|
|
27
|
+
| `result` | any | ✅ | - | 模拟的返回结果 |
|
|
28
|
+
| `type` | string | ⭐ | 'success' | 模拟类型:`'success'` 或 `'fail'` |
|
|
29
|
+
|
|
30
|
+
### 返回值
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
{
|
|
34
|
+
success: true,
|
|
35
|
+
message: "Successfully mocked wx.getSystemInfo to return success"
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 错误处理
|
|
40
|
+
|
|
41
|
+
- **未连接**: `Error: MiniProgram not connected. Call miniprogram_launch or miniprogram_connect first.`
|
|
42
|
+
- **模拟失败**: `Error: Failed to mock wx.{method}: {errorMessage}`
|
|
43
|
+
|
|
44
|
+
### 使用示例
|
|
45
|
+
|
|
46
|
+
```javascript
|
|
47
|
+
// 示例 1: 模拟 getSystemInfo 返回固定设备信息
|
|
48
|
+
await network_mock_wx_method({
|
|
49
|
+
method: "getSystemInfo",
|
|
50
|
+
result: {
|
|
51
|
+
model: "iPhone 13",
|
|
52
|
+
system: "iOS 15.0",
|
|
53
|
+
platform: "ios",
|
|
54
|
+
windowWidth: 375,
|
|
55
|
+
windowHeight: 667
|
|
56
|
+
},
|
|
57
|
+
type: "success"
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
// 后续调用 wx.getSystemInfo 会返回模拟数据
|
|
61
|
+
const info = await miniprogram_call_wx({
|
|
62
|
+
method: "getSystemInfo"
|
|
63
|
+
})
|
|
64
|
+
console.log(info.result.model) // "iPhone 13"
|
|
65
|
+
|
|
66
|
+
// 示例 2: 模拟 getLocation 失败
|
|
67
|
+
await network_mock_wx_method({
|
|
68
|
+
method: "getLocation",
|
|
69
|
+
result: {
|
|
70
|
+
errMsg: "getLocation:fail auth deny"
|
|
71
|
+
},
|
|
72
|
+
type: "fail"
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
// 示例 3: 模拟 showToast(无返回值的 API)
|
|
76
|
+
await network_mock_wx_method({
|
|
77
|
+
method: "showToast",
|
|
78
|
+
result: { errMsg: "showToast:ok" },
|
|
79
|
+
type: "success"
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
// 示例 4: 模拟 getStorage 返回预设数据
|
|
83
|
+
await network_mock_wx_method({
|
|
84
|
+
method: "getStorage",
|
|
85
|
+
result: {
|
|
86
|
+
data: { userId: 12345, token: "mock-token-abc" }
|
|
87
|
+
},
|
|
88
|
+
type: "success"
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
// 示例 5: 模拟网络断开场景
|
|
92
|
+
await network_mock_wx_method({
|
|
93
|
+
method: "uploadFile",
|
|
94
|
+
result: {
|
|
95
|
+
errMsg: "uploadFile:fail network error"
|
|
96
|
+
},
|
|
97
|
+
type: "fail"
|
|
98
|
+
})
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### 注意事项
|
|
102
|
+
|
|
103
|
+
- 💡 **适用范围**: 可模拟所有微信 API(`wx.*`),包括网络、存储、设备、媒体等
|
|
104
|
+
- ⚠️ **模拟优先级**: 模拟后,所有对该 API 的调用都会返回模拟结果,直到调用 `restore` 恢复
|
|
105
|
+
- 💡 **错误模拟**: 使用 `type: 'fail'` 模拟 API 失败场景,测试错误处理逻辑
|
|
106
|
+
- ⚠️ **会话隔离**: 模拟状态仅在当前会话有效,不影响其他会话或真实小程序
|
|
107
|
+
|
|
108
|
+
### 相关工具
|
|
109
|
+
|
|
110
|
+
- [`network_restore_wx_method`](#network_restore_wx_method) - 恢复被模拟的 API
|
|
111
|
+
- [`miniprogram_call_wx`](./miniprogram.md#miniprogram_call_wx) - 调用微信 API
|
|
112
|
+
- [`network_restore_all_mocks`](#network_restore_all_mocks) - 恢复所有模拟
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## network_restore_wx_method
|
|
117
|
+
|
|
118
|
+
恢复被模拟的微信 API 方法,使其返回原始行为。
|
|
119
|
+
|
|
120
|
+
### 参数
|
|
121
|
+
|
|
122
|
+
| 参数名 | 类型 | 必需 | 默认值 | 描述 |
|
|
123
|
+
|--------|------|------|--------|------|
|
|
124
|
+
| `method` | string | ✅ | - | 要恢复的微信 API 方法名 |
|
|
125
|
+
|
|
126
|
+
### 返回值
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
{
|
|
130
|
+
success: true,
|
|
131
|
+
message: "Successfully restored wx.getSystemInfo to original behavior"
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### 错误处理
|
|
136
|
+
|
|
137
|
+
- **未连接**: `Error: MiniProgram not connected`
|
|
138
|
+
- **恢复失败**: `Error: Failed to restore wx.{method}: {errorMessage}`
|
|
139
|
+
|
|
140
|
+
### 使用示例
|
|
141
|
+
|
|
142
|
+
```javascript
|
|
143
|
+
// 示例 1: 恢复单个 API
|
|
144
|
+
await network_mock_wx_method({
|
|
145
|
+
method: "getSystemInfo",
|
|
146
|
+
result: { model: "Mock Device" }
|
|
147
|
+
})
|
|
148
|
+
// ... 执行测试 ...
|
|
149
|
+
await network_restore_wx_method({
|
|
150
|
+
method: "getSystemInfo"
|
|
151
|
+
})
|
|
152
|
+
// 现在 getSystemInfo 返回真实设备信息
|
|
153
|
+
|
|
154
|
+
// 示例 2: 测试完成后清理模拟
|
|
155
|
+
try {
|
|
156
|
+
await network_mock_wx_method({
|
|
157
|
+
method: "getLocation",
|
|
158
|
+
result: { errMsg: "fail" },
|
|
159
|
+
type: "fail"
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
// 测试错误处理逻辑
|
|
163
|
+
await element_tap({ selector: ".get-location-btn" })
|
|
164
|
+
await assert_exists({ selector: ".error-toast" })
|
|
165
|
+
|
|
166
|
+
} finally {
|
|
167
|
+
// 确保恢复原始行为
|
|
168
|
+
await network_restore_wx_method({
|
|
169
|
+
method: "getLocation"
|
|
170
|
+
})
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// 示例 3: 切换模拟场景
|
|
174
|
+
// 先模拟成功场景
|
|
175
|
+
await network_mock_wx_method({
|
|
176
|
+
method: "request",
|
|
177
|
+
result: { data: { status: "ok" } },
|
|
178
|
+
type: "success"
|
|
179
|
+
})
|
|
180
|
+
await element_tap({ selector: ".load-btn" })
|
|
181
|
+
await assert_exists({ selector: ".success-indicator" })
|
|
182
|
+
|
|
183
|
+
// 恢复后模拟失败场景
|
|
184
|
+
await network_restore_wx_method({ method: "request" })
|
|
185
|
+
await network_mock_wx_method({
|
|
186
|
+
method: "request",
|
|
187
|
+
result: { errMsg: "fail" },
|
|
188
|
+
type: "fail"
|
|
189
|
+
})
|
|
190
|
+
await element_tap({ selector: ".load-btn" })
|
|
191
|
+
await assert_exists({ selector: ".error-message" })
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### 注意事项
|
|
195
|
+
|
|
196
|
+
- 💡 **幂等操作**: 恢复未被模拟的 API 不会报错
|
|
197
|
+
- 💡 **局部恢复**: 仅恢复指定的单个 API,不影响其他已模拟的 API
|
|
198
|
+
- ⚠️ **测试清理**: 建议在测试结束时恢复所有模拟,避免影响后续测试
|
|
199
|
+
|
|
200
|
+
### 相关工具
|
|
201
|
+
|
|
202
|
+
- [`network_mock_wx_method`](#network_mock_wx_method) - 模拟微信 API
|
|
203
|
+
- [`network_restore_all_mocks`](#network_restore_all_mocks) - 恢复所有模拟
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## network_mock_request
|
|
208
|
+
|
|
209
|
+
模拟 `wx.request` 成功返回指定数据,是 `network_mock_wx_method` 针对网络请求的便捷封装。
|
|
210
|
+
|
|
211
|
+
### 参数
|
|
212
|
+
|
|
213
|
+
| 参数名 | 类型 | 必需 | 默认值 | 描述 |
|
|
214
|
+
|--------|------|------|--------|------|
|
|
215
|
+
| `data` | any | ⭐ | `{}` | 响应数据 |
|
|
216
|
+
| `statusCode` | number | ⭐ | `200` | HTTP 状态码 |
|
|
217
|
+
| `header` | object | ⭐ | `{}` | 响应头 |
|
|
218
|
+
| `type` | string | ⭐ | `'success'` | 模拟类型(通常使用默认值) |
|
|
219
|
+
|
|
220
|
+
### 返回值
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
{
|
|
224
|
+
success: true,
|
|
225
|
+
message: "Successfully mocked wx.request to return success with status 200"
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### 错误处理
|
|
230
|
+
|
|
231
|
+
- **未连接**: `Error: MiniProgram not connected`
|
|
232
|
+
- **模拟失败**: `Error: Failed to mock wx.request: {errorMessage}`
|
|
233
|
+
|
|
234
|
+
### 使用示例
|
|
235
|
+
|
|
236
|
+
```javascript
|
|
237
|
+
// 示例 1: 模拟简单的 API 响应
|
|
238
|
+
await network_mock_request({
|
|
239
|
+
data: {
|
|
240
|
+
code: 0,
|
|
241
|
+
message: "success",
|
|
242
|
+
data: {
|
|
243
|
+
userId: 12345,
|
|
244
|
+
username: "测试用户"
|
|
245
|
+
}
|
|
246
|
+
},
|
|
247
|
+
statusCode: 200
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
// 触发请求
|
|
251
|
+
await element_tap({ selector: ".fetch-user-btn" })
|
|
252
|
+
await page_wait_for({ selector: ".user-info", timeout: 2000 })
|
|
253
|
+
|
|
254
|
+
// 验证数据显示正确
|
|
255
|
+
await assert_text({
|
|
256
|
+
selector: ".username",
|
|
257
|
+
expected: "测试用户"
|
|
258
|
+
})
|
|
259
|
+
|
|
260
|
+
// 示例 2: 模拟列表数据
|
|
261
|
+
await network_mock_request({
|
|
262
|
+
data: {
|
|
263
|
+
list: [
|
|
264
|
+
{ id: 1, name: "商品 1", price: 99 },
|
|
265
|
+
{ id: 2, name: "商品 2", price: 199 },
|
|
266
|
+
{ id: 3, name: "商品 3", price: 299 }
|
|
267
|
+
],
|
|
268
|
+
total: 3
|
|
269
|
+
}
|
|
270
|
+
})
|
|
271
|
+
|
|
272
|
+
await element_tap({ selector: ".load-products" })
|
|
273
|
+
const items = await page_query_all({ selector: ".product-item" })
|
|
274
|
+
console.log(`加载了 ${items.count} 个商品`) // 3
|
|
275
|
+
|
|
276
|
+
// 示例 3: 模拟分页响应
|
|
277
|
+
await network_mock_request({
|
|
278
|
+
data: {
|
|
279
|
+
page: 1,
|
|
280
|
+
pageSize: 10,
|
|
281
|
+
total: 100,
|
|
282
|
+
items: Array.from({ length: 10 }, (_, i) => ({
|
|
283
|
+
id: i + 1,
|
|
284
|
+
title: `文章 ${i + 1}`
|
|
285
|
+
}))
|
|
286
|
+
}
|
|
287
|
+
})
|
|
288
|
+
|
|
289
|
+
// 示例 4: 模拟 404 错误(使用 statusCode)
|
|
290
|
+
await network_mock_request({
|
|
291
|
+
data: { error: "Not Found" },
|
|
292
|
+
statusCode: 404
|
|
293
|
+
})
|
|
294
|
+
|
|
295
|
+
await element_tap({ selector: ".load-detail" })
|
|
296
|
+
await assert_exists({ selector: ".not-found-page" })
|
|
297
|
+
|
|
298
|
+
// 示例 5: 模拟自定义响应头
|
|
299
|
+
await network_mock_request({
|
|
300
|
+
data: { token: "new-token-xyz" },
|
|
301
|
+
statusCode: 200,
|
|
302
|
+
header: {
|
|
303
|
+
"Content-Type": "application/json",
|
|
304
|
+
"X-Request-Id": "mock-request-123"
|
|
305
|
+
}
|
|
306
|
+
})
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### 注意事项
|
|
310
|
+
|
|
311
|
+
- 💡 **便捷封装**: 专门用于 `wx.request`,无需手动构造响应格式
|
|
312
|
+
- ⚠️ **全局模拟**: 模拟后,所有 `wx.request` 调用都返回相同结果
|
|
313
|
+
- 💡 **状态码**: 可通过 `statusCode` 模拟不同 HTTP 状态(200, 404, 500 等)
|
|
314
|
+
- 💡 **响应格式**: `data` 字段支持任意 JSON 数据结构
|
|
315
|
+
|
|
316
|
+
### 相关工具
|
|
317
|
+
|
|
318
|
+
- [`network_mock_request_failure`](#network_mock_request_failure) - 模拟请求失败
|
|
319
|
+
- [`network_restore_request`](#network_restore_request) - 恢复请求原始行为
|
|
320
|
+
- [`miniprogram_call_wx`](./miniprogram.md#miniprogram_call_wx) - 调用 wx.request
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## network_mock_request_failure
|
|
325
|
+
|
|
326
|
+
模拟 `wx.request` 失败,用于测试网络错误、超时等异常场景的错误处理逻辑。
|
|
327
|
+
|
|
328
|
+
### 参数
|
|
329
|
+
|
|
330
|
+
| 参数名 | 类型 | 必需 | 默认值 | 描述 |
|
|
331
|
+
|--------|------|------|--------|------|
|
|
332
|
+
| `errMsg` | string | ⭐ | `'request:fail'` | 错误信息 |
|
|
333
|
+
| `errno` | number | ⭐ | `-1` | 错误码 |
|
|
334
|
+
|
|
335
|
+
### 返回值
|
|
336
|
+
|
|
337
|
+
```typescript
|
|
338
|
+
{
|
|
339
|
+
success: true,
|
|
340
|
+
message: "Successfully mocked wx.request to fail with: request:fail timeout"
|
|
341
|
+
}
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
### 错误处理
|
|
345
|
+
|
|
346
|
+
- **未连接**: `Error: MiniProgram not connected`
|
|
347
|
+
- **模拟失败**: `Error: Failed to mock wx.request failure: {errorMessage}`
|
|
348
|
+
|
|
349
|
+
### 使用示例
|
|
350
|
+
|
|
351
|
+
```javascript
|
|
352
|
+
// 示例 1: 模拟网络超时
|
|
353
|
+
await network_mock_request_failure({
|
|
354
|
+
errMsg: "request:fail timeout"
|
|
355
|
+
})
|
|
356
|
+
|
|
357
|
+
await element_tap({ selector: ".load-data-btn" })
|
|
358
|
+
await page_wait_for({ selector: ".error-toast", timeout: 2000 })
|
|
359
|
+
await assert_text({
|
|
360
|
+
selector: ".error-message",
|
|
361
|
+
expected: "网络请求超时"
|
|
362
|
+
})
|
|
363
|
+
|
|
364
|
+
// 示例 2: 模拟网络断开
|
|
365
|
+
await network_mock_request_failure({
|
|
366
|
+
errMsg: "request:fail network error",
|
|
367
|
+
errno: -2
|
|
368
|
+
})
|
|
369
|
+
|
|
370
|
+
await element_tap({ selector: ".submit-form" })
|
|
371
|
+
await assert_exists({ selector: ".offline-indicator" })
|
|
372
|
+
|
|
373
|
+
// 示例 3: 模拟服务器错误
|
|
374
|
+
await network_mock_request_failure({
|
|
375
|
+
errMsg: "request:fail server error",
|
|
376
|
+
errno: 500
|
|
377
|
+
})
|
|
378
|
+
|
|
379
|
+
// 验证重试逻辑
|
|
380
|
+
await element_tap({ selector: ".retry-btn" })
|
|
381
|
+
await page_wait_for({ timeout: 1000 })
|
|
382
|
+
await assert_exists({ selector: ".error-toast" })
|
|
383
|
+
|
|
384
|
+
// 示例 4: 测试错误恢复流程
|
|
385
|
+
// 先模拟失败
|
|
386
|
+
await network_mock_request_failure({
|
|
387
|
+
errMsg: "request:fail"
|
|
388
|
+
})
|
|
389
|
+
await element_tap({ selector: ".load-btn" })
|
|
390
|
+
await assert_exists({ selector: ".error-state" })
|
|
391
|
+
|
|
392
|
+
// 恢复正常,验证重试成功
|
|
393
|
+
await network_restore_request()
|
|
394
|
+
await network_mock_request({
|
|
395
|
+
data: { status: "ok" }
|
|
396
|
+
})
|
|
397
|
+
await element_tap({ selector: ".retry-btn" })
|
|
398
|
+
await assert_exists({ selector: ".success-state" })
|
|
399
|
+
|
|
400
|
+
// 示例 5: 测试错误日志记录
|
|
401
|
+
await network_mock_request_failure({
|
|
402
|
+
errMsg: "request:fail abort",
|
|
403
|
+
errno: -999
|
|
404
|
+
})
|
|
405
|
+
|
|
406
|
+
await element_tap({ selector: ".upload-btn" })
|
|
407
|
+
// 验证错误日志是否正确记录
|
|
408
|
+
const data = await page_get_data({ path: "errorLog" })
|
|
409
|
+
console.log("错误日志:", data.data)
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
### 注意事项
|
|
413
|
+
|
|
414
|
+
- 💡 **错误模拟**: 专门用于测试错误处理、重试逻辑、降级方案
|
|
415
|
+
- ⚠️ **真实性**: `errMsg` 应使用微信官方错误格式(`method:fail reason`)
|
|
416
|
+
- 💡 **错误码**: `errno` 可设置为任意数值,用于测试不同错误类型
|
|
417
|
+
- 💡 **组合使用**: 与 `assert_exists` 配合验证错误提示是否正确显示
|
|
418
|
+
|
|
419
|
+
### 相关工具
|
|
420
|
+
|
|
421
|
+
- [`network_mock_request`](#network_mock_request) - 模拟请求成功
|
|
422
|
+
- [`network_restore_request`](#network_restore_request) - 恢复请求
|
|
423
|
+
- [`assert_exists`](./assert.md#assert_exists) - 验证错误提示元素
|
|
424
|
+
|
|
425
|
+
---
|
|
426
|
+
|
|
427
|
+
## network_restore_request
|
|
428
|
+
|
|
429
|
+
恢复 `wx.request` 的原始行为,清除之前的模拟设置。
|
|
430
|
+
|
|
431
|
+
### 参数
|
|
432
|
+
|
|
433
|
+
无参数
|
|
434
|
+
|
|
435
|
+
### 返回值
|
|
436
|
+
|
|
437
|
+
```typescript
|
|
438
|
+
{
|
|
439
|
+
success: true,
|
|
440
|
+
message: "Successfully restored wx.request to original behavior"
|
|
441
|
+
}
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
### 错误处理
|
|
445
|
+
|
|
446
|
+
- **未连接**: `Error: MiniProgram not connected`
|
|
447
|
+
- **恢复失败**: `Error: Failed to restore wx.request: {errorMessage}`
|
|
448
|
+
|
|
449
|
+
### 使用示例
|
|
450
|
+
|
|
451
|
+
```javascript
|
|
452
|
+
// 示例 1: 测试完成后恢复
|
|
453
|
+
await network_mock_request({
|
|
454
|
+
data: { result: "mock-data" }
|
|
455
|
+
})
|
|
456
|
+
// ... 执行测试 ...
|
|
457
|
+
await network_restore_request()
|
|
458
|
+
// 现在 wx.request 发起真实网络请求
|
|
459
|
+
|
|
460
|
+
// 示例 2: 使用 try-finally 确保清理
|
|
461
|
+
try {
|
|
462
|
+
await network_mock_request_failure({
|
|
463
|
+
errMsg: "request:fail"
|
|
464
|
+
})
|
|
465
|
+
|
|
466
|
+
await element_tap({ selector: ".submit" })
|
|
467
|
+
await assert_exists({ selector: ".error-message" })
|
|
468
|
+
|
|
469
|
+
} finally {
|
|
470
|
+
await network_restore_request()
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
// 示例 3: 切换模拟场景
|
|
474
|
+
// 模拟成功场景
|
|
475
|
+
await network_mock_request({
|
|
476
|
+
data: { items: [1, 2, 3] }
|
|
477
|
+
})
|
|
478
|
+
await element_tap({ selector: ".load" })
|
|
479
|
+
await assert_exists({ selector: ".item" })
|
|
480
|
+
|
|
481
|
+
// 恢复后模拟失败场景
|
|
482
|
+
await network_restore_request()
|
|
483
|
+
await network_mock_request_failure({
|
|
484
|
+
errMsg: "request:fail timeout"
|
|
485
|
+
})
|
|
486
|
+
await element_tap({ selector: ".load" })
|
|
487
|
+
await assert_exists({ selector: ".timeout-error" })
|
|
488
|
+
|
|
489
|
+
// 示例 4: 测试套件清理
|
|
490
|
+
async function runNetworkTests() {
|
|
491
|
+
// 测试 1: 成功场景
|
|
492
|
+
await network_mock_request({ data: { ok: true } })
|
|
493
|
+
await testSuccessCase()
|
|
494
|
+
|
|
495
|
+
// 测试 2: 失败场景
|
|
496
|
+
await network_restore_request()
|
|
497
|
+
await network_mock_request_failure({ errMsg: "fail" })
|
|
498
|
+
await testFailureCase()
|
|
499
|
+
|
|
500
|
+
// 清理所有模拟
|
|
501
|
+
await network_restore_request()
|
|
502
|
+
}
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
### 注意事项
|
|
506
|
+
|
|
507
|
+
- 💡 **清理建议**: 每个测试结束后应恢复,避免影响后续测试
|
|
508
|
+
- 💡 **幂等操作**: 重复调用不会报错
|
|
509
|
+
- 💡 **特定恢复**: 仅恢复 `wx.request`,不影响其他已模拟的 API
|
|
510
|
+
|
|
511
|
+
### 相关工具
|
|
512
|
+
|
|
513
|
+
- [`network_mock_request`](#network_mock_request) - 模拟请求成功
|
|
514
|
+
- [`network_mock_request_failure`](#network_mock_request_failure) - 模拟请求失败
|
|
515
|
+
- [`network_restore_all_mocks`](#network_restore_all_mocks) - 恢复所有模拟
|
|
516
|
+
|
|
517
|
+
---
|
|
518
|
+
|
|
519
|
+
## network_restore_all_mocks
|
|
520
|
+
|
|
521
|
+
恢复所有被模拟的微信 API 方法,批量清理模拟状态。
|
|
522
|
+
|
|
523
|
+
### 参数
|
|
524
|
+
|
|
525
|
+
无参数
|
|
526
|
+
|
|
527
|
+
### 返回值
|
|
528
|
+
|
|
529
|
+
```typescript
|
|
530
|
+
{
|
|
531
|
+
success: true,
|
|
532
|
+
message: "Successfully restored 5 mocked wx methods"
|
|
533
|
+
}
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
### 错误处理
|
|
537
|
+
|
|
538
|
+
- **未连接**: `Error: MiniProgram not connected`
|
|
539
|
+
- **恢复失败**: `Error: Failed to restore all mocks: {errorMessage}`
|
|
540
|
+
|
|
541
|
+
### 使用示例
|
|
542
|
+
|
|
543
|
+
```javascript
|
|
544
|
+
// 示例 1: 测试套件结束时清理
|
|
545
|
+
async function runAllTests() {
|
|
546
|
+
try {
|
|
547
|
+
// 模拟多个 API
|
|
548
|
+
await network_mock_wx_method({
|
|
549
|
+
method: "getSystemInfo",
|
|
550
|
+
result: { model: "Mock" }
|
|
551
|
+
})
|
|
552
|
+
await network_mock_request({
|
|
553
|
+
data: { items: [] }
|
|
554
|
+
})
|
|
555
|
+
await network_mock_wx_method({
|
|
556
|
+
method: "getLocation",
|
|
557
|
+
result: { latitude: 39.9, longitude: 116.4 }
|
|
558
|
+
})
|
|
559
|
+
|
|
560
|
+
// 运行测试...
|
|
561
|
+
await testFeature1()
|
|
562
|
+
await testFeature2()
|
|
563
|
+
await testFeature3()
|
|
564
|
+
|
|
565
|
+
} finally {
|
|
566
|
+
// 一次性恢复所有模拟
|
|
567
|
+
await network_restore_all_mocks()
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
// 示例 2: 测试隔离
|
|
572
|
+
async function testWithIsolation() {
|
|
573
|
+
// 每个测试前清理所有模拟
|
|
574
|
+
await network_restore_all_mocks()
|
|
575
|
+
|
|
576
|
+
// 设置当前测试的模拟
|
|
577
|
+
await network_mock_request({
|
|
578
|
+
data: { result: "test-specific-data" }
|
|
579
|
+
})
|
|
580
|
+
|
|
581
|
+
// 运行测试...
|
|
582
|
+
await runTest()
|
|
583
|
+
|
|
584
|
+
// 测试后清理
|
|
585
|
+
await network_restore_all_mocks()
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
// 示例 3: 快速清理多个模拟
|
|
589
|
+
await network_mock_request({ data: {} })
|
|
590
|
+
await network_mock_wx_method({ method: "getStorage", result: {} })
|
|
591
|
+
await network_mock_wx_method({ method: "showToast", result: {} })
|
|
592
|
+
|
|
593
|
+
// ... 执行测试 ...
|
|
594
|
+
|
|
595
|
+
// 一次性清理,无需逐个恢复
|
|
596
|
+
await network_restore_all_mocks()
|
|
597
|
+
|
|
598
|
+
// 示例 4: 在测试钩子中使用
|
|
599
|
+
async function afterEach() {
|
|
600
|
+
// 每个测试后自动清理所有模拟
|
|
601
|
+
await network_restore_all_mocks()
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
async function testUserLogin() {
|
|
605
|
+
await network_mock_request({
|
|
606
|
+
data: { token: "test-token" }
|
|
607
|
+
})
|
|
608
|
+
// ... 测试逻辑 ...
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
async function testUserLogout() {
|
|
612
|
+
await network_mock_request({
|
|
613
|
+
data: { success: true }
|
|
614
|
+
})
|
|
615
|
+
// ... 测试逻辑 ...
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
// 每个测试后自动清理
|
|
619
|
+
await testUserLogin()
|
|
620
|
+
await afterEach()
|
|
621
|
+
|
|
622
|
+
await testUserLogout()
|
|
623
|
+
await afterEach()
|
|
624
|
+
```
|
|
625
|
+
|
|
626
|
+
### 注意事项
|
|
627
|
+
|
|
628
|
+
- 💡 **批量清理**: 尝试恢复常见的微信 API(request, storage, navigation 等)
|
|
629
|
+
- 💡 **容错处理**: 恢复未被模拟的 API 不会报错,静默跳过
|
|
630
|
+
- ⚠️ **覆盖范围**: 仅恢复预定义列表中的 API,可能无法覆盖所有已模拟的 API
|
|
631
|
+
- 💡 **测试隔离**: 建议在测试套件开始/结束时调用,确保测试间隔离
|
|
632
|
+
|
|
633
|
+
### 覆盖的 API 列表
|
|
634
|
+
|
|
635
|
+
以下微信 API 会被尝试恢复:
|
|
636
|
+
- `request`, `uploadFile`, `downloadFile`, `connectSocket`
|
|
637
|
+
- `getStorage`, `setStorage`, `removeStorage`, `clearStorage`
|
|
638
|
+
- `getSystemInfo`, `getLocation`, `chooseImage`
|
|
639
|
+
- `showToast`, `showModal`
|
|
640
|
+
- `navigateTo`, `redirectTo`
|
|
641
|
+
|
|
642
|
+
### 相关工具
|
|
643
|
+
|
|
644
|
+
- [`network_restore_wx_method`](#network_restore_wx_method) - 恢复单个 API
|
|
645
|
+
- [`network_restore_request`](#network_restore_request) - 恢复请求 API
|
|
646
|
+
- [`network_mock_wx_method`](#network_mock_wx_method) - 模拟任意 API
|
|
647
|
+
|
|
648
|
+
---
|
|
649
|
+
|
|
650
|
+
## 完整示例:网络请求模拟与测试
|
|
651
|
+
|
|
652
|
+
```javascript
|
|
653
|
+
// 场景:测试商品列表页的加载、错误处理和重试逻辑
|
|
654
|
+
async function testProductListWithNetworkMock() {
|
|
655
|
+
try {
|
|
656
|
+
// 1. 启动小程序
|
|
657
|
+
await automator_launch({
|
|
658
|
+
projectPath: "/path/to/project"
|
|
659
|
+
})
|
|
660
|
+
await miniprogram_navigate({
|
|
661
|
+
method: "navigateTo",
|
|
662
|
+
url: "/pages/product/list"
|
|
663
|
+
})
|
|
664
|
+
|
|
665
|
+
// 2. 测试加载成功场景
|
|
666
|
+
console.log("📋 测试 1: 加载成功")
|
|
667
|
+
await network_mock_request({
|
|
668
|
+
data: {
|
|
669
|
+
code: 0,
|
|
670
|
+
data: {
|
|
671
|
+
list: [
|
|
672
|
+
{ id: 1, name: "商品 A", price: 99 },
|
|
673
|
+
{ id: 2, name: "商品 B", price: 199 },
|
|
674
|
+
{ id: 3, name: "商品 C", price: 299 }
|
|
675
|
+
],
|
|
676
|
+
total: 3
|
|
677
|
+
}
|
|
678
|
+
},
|
|
679
|
+
statusCode: 200
|
|
680
|
+
})
|
|
681
|
+
|
|
682
|
+
await element_tap({ selector: ".load-products-btn" })
|
|
683
|
+
await page_wait_for({ selector: ".product-item", timeout: 2000 })
|
|
684
|
+
|
|
685
|
+
const items = await page_query_all({ selector: ".product-item" })
|
|
686
|
+
console.log(`✅ 成功加载 ${items.count} 个商品`)
|
|
687
|
+
|
|
688
|
+
// 3. 测试网络超时场景
|
|
689
|
+
console.log("📋 测试 2: 网络超时")
|
|
690
|
+
await network_restore_request()
|
|
691
|
+
await network_mock_request_failure({
|
|
692
|
+
errMsg: "request:fail timeout",
|
|
693
|
+
errno: -1
|
|
694
|
+
})
|
|
695
|
+
|
|
696
|
+
await element_tap({ selector: ".refresh-btn" })
|
|
697
|
+
await page_wait_for({ selector: ".error-toast", timeout: 2000 })
|
|
698
|
+
await assert_text({
|
|
699
|
+
selector: ".error-message",
|
|
700
|
+
expected: "网络请求超时"
|
|
701
|
+
})
|
|
702
|
+
console.log("✅ 超时错误提示正确")
|
|
703
|
+
|
|
704
|
+
// 4. 测试重试逻辑
|
|
705
|
+
console.log("📋 测试 3: 重试成功")
|
|
706
|
+
await network_restore_request()
|
|
707
|
+
await network_mock_request({
|
|
708
|
+
data: {
|
|
709
|
+
code: 0,
|
|
710
|
+
data: {
|
|
711
|
+
list: [
|
|
712
|
+
{ id: 4, name: "商品 D", price: 399 }
|
|
713
|
+
],
|
|
714
|
+
total: 1
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
})
|
|
718
|
+
|
|
719
|
+
await element_tap({ selector: ".retry-btn" })
|
|
720
|
+
await page_wait_for({ selector: ".product-item", timeout: 2000 })
|
|
721
|
+
await assert_exists({ selector: ".success-indicator" })
|
|
722
|
+
console.log("✅ 重试成功")
|
|
723
|
+
|
|
724
|
+
// 5. 测试服务器错误(500)
|
|
725
|
+
console.log("📋 测试 4: 服务器错误")
|
|
726
|
+
await network_restore_request()
|
|
727
|
+
await network_mock_request({
|
|
728
|
+
data: { error: "Internal Server Error" },
|
|
729
|
+
statusCode: 500
|
|
730
|
+
})
|
|
731
|
+
|
|
732
|
+
await element_tap({ selector: ".load-more-btn" })
|
|
733
|
+
await page_wait_for({ selector: ".server-error-message", timeout: 2000 })
|
|
734
|
+
console.log("✅ 服务器错误处理正确")
|
|
735
|
+
|
|
736
|
+
// 6. 测试空数据场景
|
|
737
|
+
console.log("📋 测试 5: 空数据")
|
|
738
|
+
await network_restore_request()
|
|
739
|
+
await network_mock_request({
|
|
740
|
+
data: {
|
|
741
|
+
code: 0,
|
|
742
|
+
data: {
|
|
743
|
+
list: [],
|
|
744
|
+
total: 0
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
})
|
|
748
|
+
|
|
749
|
+
await element_tap({ selector: ".clear-and-reload-btn" })
|
|
750
|
+
await page_wait_for({ selector: ".empty-state", timeout: 2000 })
|
|
751
|
+
await assert_text({
|
|
752
|
+
selector: ".empty-message",
|
|
753
|
+
expected: "暂无商品"
|
|
754
|
+
})
|
|
755
|
+
console.log("✅ 空状态显示正确")
|
|
756
|
+
|
|
757
|
+
// 7. 清理所有模拟
|
|
758
|
+
await network_restore_all_mocks()
|
|
759
|
+
console.log("✅ 所有测试完成,模拟已清理")
|
|
760
|
+
|
|
761
|
+
// 8. 截图留档
|
|
762
|
+
await miniprogram_screenshot({
|
|
763
|
+
filename: "network-test-complete.png"
|
|
764
|
+
})
|
|
765
|
+
|
|
766
|
+
} catch (error) {
|
|
767
|
+
console.error("❌ 测试失败:", error.message)
|
|
768
|
+
await miniprogram_screenshot({
|
|
769
|
+
filename: "network-test-error.png"
|
|
770
|
+
})
|
|
771
|
+
throw error
|
|
772
|
+
} finally {
|
|
773
|
+
// 确保清理
|
|
774
|
+
await network_restore_all_mocks()
|
|
775
|
+
await automator_disconnect()
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
testProductListWithNetworkMock()
|
|
780
|
+
```
|
|
781
|
+
|
|
782
|
+
---
|
|
783
|
+
|
|
784
|
+
## 故障排除
|
|
785
|
+
|
|
786
|
+
### 问题 1: 模拟不生效
|
|
787
|
+
|
|
788
|
+
**错误**: 模拟后仍然发起真实网络请求
|
|
789
|
+
|
|
790
|
+
**解决方案**:
|
|
791
|
+
1. 确认模拟在请求前已设置
|
|
792
|
+
2. 检查 `method` 参数是否正确(大小写敏感)
|
|
793
|
+
3. 验证小程序代码是否使用了 `wx.request`(而非 `fetch` 等其他方法)
|
|
794
|
+
|
|
795
|
+
```javascript
|
|
796
|
+
// ❌ 错误:模拟在请求后设置
|
|
797
|
+
await element_tap({ selector: ".load-btn" })
|
|
798
|
+
await network_mock_request({ data: {} }) // 太晚了
|
|
799
|
+
|
|
800
|
+
// ✅ 正确:先模拟,后触发
|
|
801
|
+
await network_mock_request({ data: {} })
|
|
802
|
+
await element_tap({ selector: ".load-btn" })
|
|
803
|
+
```
|
|
804
|
+
|
|
805
|
+
### 问题 2: 多次模拟冲突
|
|
806
|
+
|
|
807
|
+
**错误**: 第二次模拟覆盖了第一次
|
|
808
|
+
|
|
809
|
+
**解决方案**:
|
|
810
|
+
1. 每次模拟前先恢复之前的模拟
|
|
811
|
+
2. 使用 `network_restore_request()` 清除旧模拟
|
|
812
|
+
|
|
813
|
+
```javascript
|
|
814
|
+
// ❌ 错误:直接覆盖可能导致混乱
|
|
815
|
+
await network_mock_request({ data: { a: 1 } })
|
|
816
|
+
await network_mock_request({ data: { b: 2 } }) // 覆盖了前一个
|
|
817
|
+
|
|
818
|
+
// ✅ 正确:先恢复,再模拟
|
|
819
|
+
await network_mock_request({ data: { a: 1 } })
|
|
820
|
+
await testScenario1()
|
|
821
|
+
|
|
822
|
+
await network_restore_request() // 清除
|
|
823
|
+
await network_mock_request({ data: { b: 2 } })
|
|
824
|
+
await testScenario2()
|
|
825
|
+
```
|
|
826
|
+
|
|
827
|
+
### 问题 3: 忘记清理模拟
|
|
828
|
+
|
|
829
|
+
**错误**: 模拟影响了后续测试
|
|
830
|
+
|
|
831
|
+
**解决方案**:
|
|
832
|
+
1. 使用 `try-finally` 确保清理
|
|
833
|
+
2. 在测试结束时调用 `network_restore_all_mocks()`
|
|
834
|
+
|
|
835
|
+
```javascript
|
|
836
|
+
// ❌ 错误:异常时未清理
|
|
837
|
+
await network_mock_request({ data: {} })
|
|
838
|
+
await runTest()
|
|
839
|
+
await network_restore_request() // 如果 runTest 抛出异常,这行不会执行
|
|
840
|
+
|
|
841
|
+
// ✅ 正确:使用 finally 确保清理
|
|
842
|
+
try {
|
|
843
|
+
await network_mock_request({ data: {} })
|
|
844
|
+
await runTest()
|
|
845
|
+
} finally {
|
|
846
|
+
await network_restore_all_mocks()
|
|
847
|
+
}
|
|
848
|
+
```
|
|
849
|
+
|
|
850
|
+
---
|
|
851
|
+
|
|
852
|
+
## 技术细节
|
|
853
|
+
|
|
854
|
+
### 模拟机制
|
|
855
|
+
|
|
856
|
+
- **原理**: 使用 `miniprogram-automator` 的 `mockWxMethod` API 劫持微信 API 调用
|
|
857
|
+
- **作用域**: 仅影响当前自动化会话,不影响真实小程序或其他会话
|
|
858
|
+
- **优先级**: 模拟优先于原始 API,直到显式恢复
|
|
859
|
+
|
|
860
|
+
### 模拟状态管理
|
|
861
|
+
|
|
862
|
+
- **存储**: 模拟状态由 `miniprogram-automator` SDK 内部管理
|
|
863
|
+
- **生命周期**: 从设置模拟到恢复模拟,或会话结束
|
|
864
|
+
- **清理**: 会话断开时自动清理所有模拟
|
|
865
|
+
|
|
866
|
+
### 常见模拟场景
|
|
867
|
+
|
|
868
|
+
| 场景 | 工具 | 用途 |
|
|
869
|
+
|------|------|------|
|
|
870
|
+
| 成功响应 | `network_mock_request` | 测试正常流程 |
|
|
871
|
+
| 网络超时 | `network_mock_request_failure` | 测试超时处理 |
|
|
872
|
+
| 服务器错误 | `network_mock_request` + `statusCode: 500` | 测试错误处理 |
|
|
873
|
+
| 空数据 | `network_mock_request` + `data: { list: [] }` | 测试空状态 |
|
|
874
|
+
| 权限拒绝 | `network_mock_wx_method` + `type: 'fail'` | 测试权限错误 |
|
|
875
|
+
|
|
876
|
+
---
|
|
877
|
+
|
|
878
|
+
**相关文档**:
|
|
879
|
+
- [MiniProgram API](./miniprogram.md) - 调用微信 API
|
|
880
|
+
- [Assert API](./assert.md) - 验证模拟效果
|
|
881
|
+
- [使用示例](../../examples/03-network-testing.md) - 网络测试示例
|
|
882
|
+
|
|
883
|
+
**最后更新**: 2025-10-03
|