A value-based test checks what code gives back. Call a function through its entry point, capture its return value, and assert that value. Return values are direct outputs, so this is usually the simplest kind of exit point to test: the test observes behavior from the outside rather than how the behavior was produced. section 1.5 section 8.3.1
The key question is not “Which internal function ran?” but “What visible result did the caller receive?” Testing a protected helper call couples a test to an implementation detail. Renaming, removing, or reorganizing that helper can break the test even when the observable behavior remains correct. When a public function returns the needed information, assert that result instead. section 8.3.1 section 5.7
Choose the exit point that matches the behavior you need to prove:
- Use a value-based test when calling the unit returns a value that reveals success, failure, or computed output. section 1.5 section 8.3.1
- Use a state-based test when a call changes a visible sibling property or function result instead of returning the relevant information. section 1.5 section 8.3.1
- Reserve interaction tests with mocks for third-party dependencies when no return value or visible state can prove the behavior. section 5.6.1 section 5.7
Test the verifier’s result, not its helper call
A password verifier can call an internal findFailedRules helper and then return true or false from verify(input). A durable test calls verify("abc") and asserts the boolean result. It does not replace findFailedRules with a mock or assert that the helper was called, because the helper is not the externally meaningful exit point. section 8.3.1
Listing 6.4 Integration test with async/await
test("NETWORK REQUIRED2 (await): correct content, true", async () => {
const result = await samples.isWebsiteAliveWithAsyncAwait();
expect(result.success).toBe(true);
expect(result.status).toBe("ok");
});
Async/await can keep an asynchronous result test in the familiar value-based shape: await the returned result, then assert its visible fields. section 6.1.3
Value-based tests are not limited to synchronous functions. With async/await, await the operation and inspect the resolved result using the same Arrange-Act-Assert flow. The underlying operation can still be asynchronous enough to count as an integration test, but the test is clearer than callback-based assertions. section 6.1.3
