Skip to content

test_runner: support object property mocking #58438

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jun 9, 2025

Conversation

idango10
Copy link
Contributor

@idango10 idango10 commented May 23, 2025

Fixes: #58322


This PR adds object property mocking to the test runner.

Example usage:

test('mocks a property value', (t) => {
  const obj = { foo: 42 };
  const prop = t.mock.property(obj, 'foo', 100);

  assert.strictEqual(obj.foo, 100);
  assert.strictEqual(prop.mock.accessCount(), 1);
  assert.strictEqual(prop.mock.accesses[0].type, 'get');
  assert.strictEqual(prop.mock.accesses[0].value, 100);

  obj.foo = 200;
  assert.strictEqual(prop.mock.accessCount(), 2);
  assert.strictEqual(prop.mock.accesses[1].type, 'set');
  assert.strictEqual(prop.mock.accesses[1].value, 200);

  prop.mock.restore();
  assert.strictEqual(obj.foo, 42);
});

@nodejs-github-bot
Copy link
Collaborator

Review requested:

  • @nodejs/test_runner

@nodejs-github-bot nodejs-github-bot added needs-ci PRs that need a full CI run. test_runner Issues and PRs related to the test runner subsystem. labels May 23, 2025
Copy link

codecov bot commented May 23, 2025

Codecov Report

Attention: Patch coverage is 99.38650% with 1 line in your changes missing coverage. Please review.

Project coverage is 90.22%. Comparing base (d96d57d) to head (e1d143f).
Report is 135 commits behind head on main.

Files with missing lines Patch % Lines
lib/internal/test_runner/mock/mock.js 99.38% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #58438      +/-   ##
==========================================
+ Coverage   90.20%   90.22%   +0.01%     
==========================================
  Files         635      635              
  Lines      187174   187774     +600     
  Branches    36751    36866     +115     
==========================================
+ Hits       168846   169421     +575     
- Misses      11120    11126       +6     
- Partials     7208     7227      +19     
Files with missing lines Coverage Δ
lib/internal/test_runner/mock/mock.js 99.28% <99.38%> (+0.02%) ⬆️

... and 76 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

@cjihrig cjihrig left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this. I think this is a good start, but I'd like to see it more unified with the rest of the mocking framework (particularly mock.method() since the use case is so similar)

idango10 added 2 commits May 24, 2025 05:21
- `mock.value` -> `mock.property`.
- `value` parameter is now optional.
- add `MockValueContext` section to the docs.
- align API with the rest of the mocking framework.
- add more tests
@idango10
Copy link
Contributor Author

Thanks for working on this. I think this is a good start, but I'd like to see it more unified with the rest of the mocking framework (particularly mock.method() since the use case is so similar)

Thanks for the thorough review! 😃
I think I've addressed all your comments and pushed the changes. Let me know if there's anything else you'd like me to tweak.

…provided

and rename property mock tests to align with the ones in `test-runner-mocking.js`.
@benjamingr
Copy link
Member

Hey, welcome @idango10 nice seeing you around here, I trust Colin and agree with his feedback.

Copy link
Contributor

@cjihrig cjihrig left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking pretty good to me. Two notes:

  1. It doesn't appear that a mockImplementationOnce() equivalent is implemented.
  2. Can we add a test for explicitly mocking a property as undefined. This will definitely come up eventually, and I don't think the current implementation can support it. It might take a little bit of work to distinguish between the "explicit undefined" and "use the previously existing value" use cases.

…d not passing value parameter at all

and add test for undefined mock property value
@idango10
Copy link
Contributor Author

This is looking pretty good to me. Two notes:

  1. It doesn't appear that a mockImplementationOnce() equivalent is implemented.
  2. Can we add a test for explicitly mocking a property as undefined. This will definitely come up eventually, and I don't think the current implementation can support it. It might take a little bit of work to distinguish between the "explicit undefined" and "use the previously existing value" use cases.
  1. I'm wondering about how we should implement this. It's pretty problematic since accesses includes both get and set actions. For gets we have no problem, but set is a different case. If a set happens at the same access index, it will consume the "once" value and change the mocked property to the value we only intended to use once.
  2. Great catch, it was indeed a bug. Fixed and added a test for it.

@cjihrig
Copy link
Contributor

cjihrig commented May 26, 2025

I'm wondering about how we should implement this. It's pretty problematic since accesses includes both get and set actions. For gets we have no problem, but set is a different case. If a set happens at the same access index, it will consume the "once" value and change the mocked property to the value we only intended to use once.

Personally, I would just let it apply to both sets and gets and document the caveat you mentioned here. We could make it only apply to gets, but that would be inconsistent with how the rest of the implementation works and we would still need to document that caveat.

@idango10
Copy link
Contributor Author

I'm wondering about how we should implement this. It's pretty problematic since accesses includes both get and set actions. For gets we have no problem, but set is a different case. If a set happens at the same access index, it will consume the "once" value and change the mocked property to the value we only intended to use once.

Personally, I would just let it apply to both sets and gets and document the caveat you mentioned here. We could make it only apply to gets, but that would be inconsistent with how the rest of the implementation works and we would still need to document that caveat.

I added mockImplementationOnce() which applies to both sets and gets, as you suggested. Please let me know if there's anything else I should change 😃

doc/api/test.md Outdated
* `object` {Object} The object whose value is being mocked.
* `propertyName` {string|symbol} The identifier of the property on `object` to mock.
* `value` {any} An optional value used as the mock value
for `object[valueName]`. **Default:** The original property value.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
for `object[valueName]`. **Default:** The original property value.
for `object[propertyName]`. **Default:** The original property value.

@idango10
Copy link
Contributor Author

idango10 commented Jun 5, 2025

Hey @cjihrig, hope you're doing well! Sorry to ping you, but I wanted to check if you've had a chance to look at my latest changes. Please let me know if anything needs tweaking. Thanks a lot!

@cjihrig cjihrig added the request-ci Add this label to start a Jenkins CI on a PR. label Jun 5, 2025
@github-actions github-actions bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Jun 5, 2025
@nodejs-github-bot
Copy link
Collaborator

@atlowChemi atlowChemi added author ready PRs that have at least one approval, no pending requests for changes, and a CI started. commit-queue-squash Add this label to instruct the Commit Queue to squash all the PR commits into the first one. labels Jun 5, 2025
@ljharb
Copy link
Member

ljharb commented Jun 5, 2025

it seems like the API just takes a value - what about getters/setters, enumerability, writability?

@atlowChemi atlowChemi added semver-minor PRs that contain new features and should be released in the next minor version. notable-change PRs with changes that should be highlighted in changelogs. labels Jun 5, 2025
Copy link
Contributor

github-actions bot commented Jun 5, 2025

The notable-change PRs with changes that should be highlighted in changelogs. label has been added by @atlowChemi.

Please suggest a text for the release notes if you'd like to include a more detailed summary, then proceed to update the PR description with the text or a link to the notable change suggested text comment. Otherwise, the commit will be placed in the Other Notable Changes section.

@peteduel
Copy link

peteduel commented Jun 6, 2025

it seems like the API just takes a value - what about getters/setters, enumerability, writability?

Mocking a value for testing why would modification of property descriptors be desirable?

@benjamingr benjamingr added the commit-queue Add this label to land a pull request using GitHub Actions. label Jun 9, 2025
@nodejs-github-bot nodejs-github-bot removed the commit-queue Add this label to land a pull request using GitHub Actions. label Jun 9, 2025
@nodejs-github-bot nodejs-github-bot merged commit 905a722 into nodejs:main Jun 9, 2025
76 checks passed
@nodejs-github-bot
Copy link
Collaborator

Landed in 905a722

@idango10 idango10 deleted the idango/mock-value branch June 9, 2025 17:58
@ljharb
Copy link
Member

ljharb commented Jun 9, 2025

@peteduel because enumerability and writability are all things that should be tested?

seriousme pushed a commit to seriousme/node that referenced this pull request Jun 10, 2025
PR-URL: nodejs#58438
Fixes: nodejs#58322
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
author ready PRs that have at least one approval, no pending requests for changes, and a CI started. commit-queue-squash Add this label to instruct the Commit Queue to squash all the PR commits into the first one. needs-ci PRs that need a full CI run. notable-change PRs with changes that should be highlighted in changelogs. semver-minor PRs that contain new features and should be released in the next minor version. test_runner Issues and PRs related to the test runner subsystem.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add mock.value() to mock a value
8 participants