Skip to content
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

Remember invocations #474

Merged
merged 3 commits into from
Mar 9, 2020
Merged

Conversation

nitishr
Copy link
Contributor

@nitishr nitishr commented Mar 6, 2020

Fixes #473. Earlier, whenever you qualified an Expectation with a cardinality, a new Cardinality instance would be replace the old one. 59454a8 moved the invocations recording to Cardinality, which then meant that the invocations recorded prior to updating cardinality would get discarded along with the Cardinality instance, effectively being forgotten.

We now update the quantifiers of the same Cardinality instance for each Expectation in order to persist the recording of invocations across updates to cardinality.

Copy link
Member

@floehopper floehopper left a comment

Choose a reason for hiding this comment

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

Thanks so much for finding the time to investigate #473 and for submitting this PR - I really appreciate it!

I've added some review comments inline which I think it would be good to address before merging. Although I haven't had loads of time to look through the changes as carefully as I would like, so I apologise if I've misunderstood something.

I think it's probably outside the scope of this PR, but I wonder whether e.g. calling Expectation#at_most should affect the required number of calls. I think I'm right in saying that in the following code, the call to Expectation#at_most overrides the required number of calls set by the call to Expectation#at_least which doesn't seem quite right:

foo.expects(:bar).at_least(2).at_most(4)

I suspect this may have always been the behaviour and I don't remember anyone complaining about it, but perhaps it would be good to tighten things up a bit. What do you think?

lib/mocha/cardinality.rb Show resolved Hide resolved
lib/mocha/cardinality.rb Outdated Show resolved Hide resolved
lib/mocha/expectation.rb Outdated Show resolved Hide resolved
lib/mocha/cardinality.rb Show resolved Hide resolved
lib/mocha/expectation.rb Show resolved Hide resolved
... in order to make a single Cardinality instance persist across
updates to expectation cardinality. This include a 'times' method. To
make space for it, the existing protected 'times' method has been
renamed to 'count'.
Fixes freerange#473. Earlier, whenever you qualified an Expectation with a
cardinality, a new Cardinality instance would replace the old one.
The moving of invocations recording to Cardinality in 59454a8 then meant
that the invocations recorded prior to updating cardinality would get
discarded along with the Cardinality instance, effectively being
forgotten.

We now update the quantifiers of the same Cardinality instance for each
Expectation in order to persist the recording of invocations across
updates to cardinality.
The at_{least,most}_once methods simply delegate to at_least, and
at_least returns self. So, ending with a call to at_least means we don't
need to end with self in order to return self.
Copy link
Contributor Author

@nitishr nitishr left a comment

Choose a reason for hiding this comment

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

[...] I wonder whether e.g. calling Expectation#at_most should affect the required number of calls. I think I'm right in saying that in the following code, the call to Expectation#at_most overrides the required number of calls set by the call to Expectation#at_least which doesn't seem quite right:

foo.expects(:bar).at_least(2).at_most(4)

You're right in your observation. And I think intuitively, the above code would seem to be equivalent to

foo.expects(:bar).times(2..4)

However, our current rule is: Every cardinality-setting method defines both lower and upper bounds, thus replaces/overrides any earlier cardinality wholesale. This might even be worth documenting.

Making the above code respect intuition would mean complicating that rule, and I think it get very complicated very quickly. For instance, what's the outcome of the below?

foo.expect(:bar).exactly(2).at_most(4)

Most such 'combinations' yield no sensible/intuitive outcome. So, I think rather than supporting 'combinations', we should keep it simple and stick with 'overrides'.

lib/mocha/cardinality.rb Show resolved Hide resolved
lib/mocha/cardinality.rb Show resolved Hide resolved
lib/mocha/expectation.rb Show resolved Hide resolved
lib/mocha/expectation.rb Show resolved Hide resolved
@floehopper
Copy link
Member

@nitishr Thanks again for identifying the problem in #473 and for taking the time to submit this PR and address my comments.

However, our current rule is: Every cardinality-setting method defines both lower and upper bounds, thus replaces/overrides any earlier cardinality wholesale. This might even be worth documenting.

Agreed. I've opened #476 to address this.

Most such 'combinations' yield no sensible/intuitive outcome. So, I think rather than supporting 'combinations', we should keep it simple and stick with 'overrides'.

Agreed. Thanks for considering my suggestion and for pointing out the flaws in it!

I'll try to get this merged shortly.

@floehopper floehopper merged commit 729d43d into freerange:master Mar 9, 2020
kevindew added a commit to alphagov/whitehall that referenced this pull request Apr 12, 2022
Creating an organisation causes a call to
Whitehall::PublishingApi.patch_links due to Active Record callbacks.

In Mocha 1.12.0 there was a change (presumably
freerange/mocha#474) that causes the test to
start failing in it's previous incantation. My understanding is that
this fail occurs because the organisation is being created after the
mock (`expects`) is applied to Whitehall::PublishingApi, which leads to
the test failing because it thinks the `patch_links` method has been
invoked twice.

As per:

```
Error:
patch_links::#organisations#test_patches_links_for_organisations:
DRb::DRbRemoteError: unexpected invocation: Whitehall::PublishingApi.patch_links(#<Organisation:0x3e620>, {:bulk_publishing => true})
unsatisfied expectations:
- expected exactly once, invoked twice: Whitehall::PublishingApi.patch_links(#<Organisation:0x3e530>, {:bulk_publishing => true})
satisfied expectations:
- allowed any number of times, invoked never: #<User:0x3e490>.persisted?(any_parameters)
- allowed any number of times, invoked never: #<User:0x3e490>.id(any_parameters)
- allowed any number of times, invoked never: Services.asset_manager(any_parameters)
 (Minitest::Assertion)
    lib/tasks/publishing_api.rake:152:in `block (4 levels) in <top (required)>'
    lib/tasks/publishing_api.rake:149:in `each'
    lib/tasks/publishing_api.rake:149:in `each_with_index'
    lib/tasks/publishing_api.rake:149:in `block (3 levels) in <top (required)>'
    test/unit/tasks/publishing_api_test.rb:165:in `block (3 levels) in <class:PublishingApiRake>'
```
kevindew added a commit to alphagov/whitehall that referenced this pull request Apr 14, 2022
Creating an organisation causes a call to
Whitehall::PublishingApi.patch_links due to Active Record callbacks.

In Mocha 1.12.0 there was a change (presumably
freerange/mocha#474) that causes the test to
start failing in it's previous incantation. My understanding is that
this fail occurs because the organisation is being created after the
mock (`expects`) is applied to Whitehall::PublishingApi, which leads to
the test failing because it thinks the `patch_links` method has been
invoked twice.

As per:

```
Error:
patch_links::#organisations#test_patches_links_for_organisations:
DRb::DRbRemoteError: unexpected invocation: Whitehall::PublishingApi.patch_links(#<Organisation:0x3e620>, {:bulk_publishing => true})
unsatisfied expectations:
- expected exactly once, invoked twice: Whitehall::PublishingApi.patch_links(#<Organisation:0x3e530>, {:bulk_publishing => true})
satisfied expectations:
- allowed any number of times, invoked never: #<User:0x3e490>.persisted?(any_parameters)
- allowed any number of times, invoked never: #<User:0x3e490>.id(any_parameters)
- allowed any number of times, invoked never: Services.asset_manager(any_parameters)
 (Minitest::Assertion)
    lib/tasks/publishing_api.rake:152:in `block (4 levels) in <top (required)>'
    lib/tasks/publishing_api.rake:149:in `each'
    lib/tasks/publishing_api.rake:149:in `each_with_index'
    lib/tasks/publishing_api.rake:149:in `block (3 levels) in <top (required)>'
    test/unit/tasks/publishing_api_test.rb:165:in `block (3 levels) in <class:PublishingApiRake>'
```
kevindew added a commit to alphagov/whitehall that referenced this pull request Apr 19, 2022
Creating an organisation causes a call to
Whitehall::PublishingApi.patch_links due to Active Record callbacks.

In Mocha 1.12.0 there was a change (presumably
freerange/mocha#474) that causes the test to
start failing in it's previous incantation. My understanding is that
this fail occurs because the organisation is being created after the
mock (`expects`) is applied to Whitehall::PublishingApi, which leads to
the test failing because it thinks the `patch_links` method has been
invoked twice.

As per:

```
Error:
patch_links::#organisations#test_patches_links_for_organisations:
DRb::DRbRemoteError: unexpected invocation: Whitehall::PublishingApi.patch_links(#<Organisation:0x3e620>, {:bulk_publishing => true})
unsatisfied expectations:
- expected exactly once, invoked twice: Whitehall::PublishingApi.patch_links(#<Organisation:0x3e530>, {:bulk_publishing => true})
satisfied expectations:
- allowed any number of times, invoked never: #<User:0x3e490>.persisted?(any_parameters)
- allowed any number of times, invoked never: #<User:0x3e490>.id(any_parameters)
- allowed any number of times, invoked never: Services.asset_manager(any_parameters)
 (Minitest::Assertion)
    lib/tasks/publishing_api.rake:152:in `block (4 levels) in <top (required)>'
    lib/tasks/publishing_api.rake:149:in `each'
    lib/tasks/publishing_api.rake:149:in `each_with_index'
    lib/tasks/publishing_api.rake:149:in `block (3 levels) in <top (required)>'
    test/unit/tasks/publishing_api_test.rb:165:in `block (3 levels) in <class:PublishingApiRake>'
```
kevindew added a commit to alphagov/whitehall that referenced this pull request Apr 22, 2022
Creating an organisation causes a call to
Whitehall::PublishingApi.patch_links due to Active Record callbacks.

In Mocha 1.12.0 there was a change (presumably
freerange/mocha#474) that causes the test to
start failing in it's previous incantation. My understanding is that
this fail occurs because the organisation is being created after the
mock (`expects`) is applied to Whitehall::PublishingApi, which leads to
the test failing because it thinks the `patch_links` method has been
invoked twice.

As per:

```
Error:
patch_links::#organisations#test_patches_links_for_organisations:
DRb::DRbRemoteError: unexpected invocation: Whitehall::PublishingApi.patch_links(#<Organisation:0x3e620>, {:bulk_publishing => true})
unsatisfied expectations:
- expected exactly once, invoked twice: Whitehall::PublishingApi.patch_links(#<Organisation:0x3e530>, {:bulk_publishing => true})
satisfied expectations:
- allowed any number of times, invoked never: #<User:0x3e490>.persisted?(any_parameters)
- allowed any number of times, invoked never: #<User:0x3e490>.id(any_parameters)
- allowed any number of times, invoked never: Services.asset_manager(any_parameters)
 (Minitest::Assertion)
    lib/tasks/publishing_api.rake:152:in `block (4 levels) in <top (required)>'
    lib/tasks/publishing_api.rake:149:in `each'
    lib/tasks/publishing_api.rake:149:in `each_with_index'
    lib/tasks/publishing_api.rake:149:in `block (3 levels) in <top (required)>'
    test/unit/tasks/publishing_api_test.rb:165:in `block (3 levels) in <class:PublishingApiRake>'
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Change in partial expectation evaluation time?
2 participants