基于Jasmine框架的异步函数API测试代码相关技术咨询
Hey there! Let’s break down your partial Jasmine async API test code, cover common pitfalls you might run into, and share actionable improvements to make your tests more reliable.
First, here’s your formatted code snippet for clarity:
'use strict'; var unitID = 0; var getById = function(generalOptions, specificOptions) { describe('API tests for: ' + specificOptions.name, function() { var url = generalOptions.baseUrl + specificOptions.route; // 获取全部条目 it('= = = GET ALL test for ' + specificOptions.name + ' return status code 200', function(done) { generalOptions.request.get({ url: url }, function(error, response, body) { expect(response.statusCode).toBe(200); expect(JSON.parse(body)).not.toBeFalsy(); // 你提到的if...分支在这里 done(); // 注意:必须确保所有路径都调用done! }); }); }); };
Critical Fixes & Best Practices
Always call
done()in all code paths
Your current code has anif...branch that you didn’t finish writing. If you forget to calldone()inside that branch (or if an error occurs before reaching it), Jasmine will hang indefinitely waiting for the test to complete. Wrap your assertions in a try/catch to handle errors and ensuredone()is always invoked:it('= = = GET ALL test for ' + specificOptions.name + ' return status code 200', function(done) { generalOptions.request.get({ url: url }, function(error, response, body) { try { if (error) throw new Error(error.message); expect(response.statusCode).toBe(200); const parsedBody = JSON.parse(body); expect(parsedBody).not.toBeFalsy(); // 处理你的if分支逻辑 done(); } catch (err) { done.fail(err); // 把错误传递给Jasmine,标记测试失败 } }); });Avoid global variable pollution
TheunitIDvariable is declared outside thedescribeblock, which means it will be shared across all tests that use this function. This can cause unexpected state leaks between test runs. Move it inside thedescribeblock or initialize it withbeforeEach:describe('API tests for: ' + specificOptions.name, function() { let unitID = 0; // 限定在describe作用域内 var url = generalOptions.baseUrl + specificOptions.route; beforeEach(() => { unitID = 0; // 每次测试前重置 }); // ...测试用例 });Handle JSON parsing safely
CallingJSON.parse(body)directly will throw an error if the API returns invalid JSON. Add a check for the response’sContent-Typeheader first, and wrap parsing in a try/catch:expect(response.headers['content-type']).toContain('application/json'); let parsedBody; try { parsedBody = JSON.parse(body); } catch (parseErr) { throw new Error(`Failed to parse response body: ${parseErr.message}`); } expect(parsedBody).not.toBeFalsy();Simplify with async/await
Jasmine supports async functions, which eliminate the need for thedonecallback entirely. If yourgeneralOptions.requestlibrary returns promises (or you can promisify it withutil.promisify), your code becomes much cleaner:const util = require('util'); const getRequest = util.promisify(generalOptions.request.get); it('= = = GET ALL test for ' + specificOptions.name + ' return status code 200', async function() { const response = await getRequest({ url: url }); expect(response.statusCode).toBe(200); expect(response.headers['content-type']).toContain('application/json'); const parsedBody = JSON.parse(response.body); expect(parsedBody).not.toBeFalsy(); });
Common Questions You Might Have
Q: My test is timing out even though the API responds?
A: This almost always meansdone()isn’t being called in one of your code paths (like an error branch or anelseclause). Use the try/catch pattern above to ensure all paths lead to eitherdone()ordone.fail().Q: How do I test error scenarios (e.g., 404, 500)?
A: Usedone.fail()in the error callback, or with async/await, wrap the call in aexpect().rejects.toThrow()block:it('should return 404 for invalid ID', async function() { await expect(getRequest({ url: `${url}/invalid-id` })).rejects.toHaveProperty('statusCode', 404); });
内容的提问来源于stack exchange,提问作者Anri

