How can I test async code that succeeds, rejects, or returns empty data?
Quick answer
Use a controlled test double so the async function receives predictable local data instead of calling a real service. Write separate tests for a normal result, a rejected operation, and a successful operation that returns an empty collection. Decide what each outcome should mean for your function, then assert its returned value or error. A stub can provide controlled data and simulate failures and edge cases; use the setup required by your chosen test framework. [S1]
The question, the details, the next step.
A practical checklist
Write down the expected public result for success, rejection, and empty data.
Use a local stub with a small, controlled fixture instead of live credentials or personal data.
Give each test its own dependency behavior and assert the awaited result or rejection.
Treat an empty result separately from a rejected operation.
Use the setup and assertion syntax documented for your project’s test framework.
A few more useful answers
Should an empty result count as a failure?
Only if that matches the function’s intended contract. Test an empty resolved value separately so it is not confused with a rejected operation.
Do I need a mock, or is a stub enough?
A stub is enough when you need to supply controlled results. A mock may be useful when the test also needs to record calls. [S1]
Can I copy the example assertions directly into my test runner?
No: the example states the assertion intent in framework-neutral pseudocode. Check your chosen runner’s current setup and syntax; the cited guidance discusses Node.js’s built-in runner, Jest, and Vitest. [S1]
Sources
References used for this guide.
- [S1] Microsoft guidance on JavaScript SDK tests and test doubles learn.microsoft.com · Checked
