Skip to content

Print mock history#2673

Merged
nohwnd merged 8 commits into
mainfrom
mock-history
Jun 23, 2026
Merged

Print mock history#2673
nohwnd merged 8 commits into
mainfrom
mock-history

Conversation

@nohwnd

@nohwnd nohwnd commented Jan 23, 2026

Copy link
Copy Markdown
Member

When Should -Invoke fails, the error message now includes a history of all mock invocations, showing which calls matched the filter and which didn't, along with the file and line where the mock behavior was defined. This makes it much easier to debug why an assertion failed.

Examples

Count mismatch — calls were made but not enough:

Expected Get-Process to be called 3 times exactly, but was called 2 times
Performed invocations:
  [*] Get-Process -Name @('code') from tests/Api.Tests.ps1:42
  [*] Get-Process -Name @('pwsh') from tests/Api.Tests.ps1:42

Filter mismatch — calls were made but none matched the filter:

Expected Write-Host to be called at least 1 times, but was called 0 times
Performed invocations:
  [ ] Write-Host -Object @('hello') from tests/Logger.Tests.ps1:15
  [ ] Write-Host -Object @('world') from tests/Logger.Tests.ps1:15

Zero calls — mock was never invoked:

Expected Invoke-RestMethod to be called 1 times exactly, but was called 0 times
Performed invocations:
  <none>

[*] = matched the filter, [ ] = did not match. Each invocation shows the file:line of the -MockWith scriptblock that handled it.

Changes

  • Format-MockCallHistoryMessage in Mock.ps1 builds the invocation history with markers and location
  • Uses foreach keyword instead of ForEach-Object for performance
  • Dedicated tests for history output formatting

Fixes #2673

@HeyItsGilbert

HeyItsGilbert commented Jan 26, 2026

Copy link
Copy Markdown

Would + and - in the front of the matching calls be better? Either way I think putting the identifier at the beginning may help if the commands are super long.

Another nice to have would be identifying where the call came from (e.g. line number, file, etc.). This could be helpful in identifying mocked calls that are similar but for some reason the logic branch didn't hit them.

I wonder (in another PR) if we flipped this on its head, and made it so we could evaluate what would be mocked (so read in the test file first) and then parsed a script and returned a list of mocked (with what criteria passed/failed). I know that would help me for sure. The other nice thing with this is that if we failed to properly mock, we would know that before running potentially system impacting commands.

@nohwnd

nohwnd commented Jan 29, 2026

Copy link
Copy Markdown
Member Author

Would + and - in the front of the matching calls be better? Either way I think putting the identifier at the beginning may help if the commands are super long.

+ and - are already used for the test results, I think it is more confusing.

What else shows success or not success , call or not call, that is not + or -?

It should also be easy to grasp and hard misunderstand, and the format should work when there are 0 calls.

Another nice to have would be identifying where the call came from (e.g. line number, file, etc.). This could be helpful in identifying mocked calls that are similar but for some reason the logic branch didn't hit them.

I agree. Seeing where the mock call came from would be nice. There is even more info that can be printed, e.g. why it did not match ( we cannot explain exactly why, but can at least show the filter that was used).

I wonder (in another PR) if we flipped this on its head, and made it so we could evaluate what would be mocked (so read in the test file first) and then parsed a script and returned a list of mocked (with what criteria passed/failed).

I feel like all of this info already is in the debugging log. And it is a lot of info to help you debug mock calls that behave differently than you thought.

The other nice thing with this is that if we failed to properly mock, we would know that before running potentially system impacting commands.

In version 6 the mocks will never fall through to the real command so this is less of a concern, but I see it still apply when you for example don't mock correctly in a module scope. It is hard to protect you from that though, as it means we would have to push mock into every single mock scope (or hijack the execution).

@nohwnd

nohwnd commented Jan 29, 2026

Copy link
Copy Markdown
Member Author
image

trying your suggestions

@nohwnd

nohwnd commented Jan 29, 2026

Copy link
Copy Markdown
Member Author

I think I need to add the location (describe / it) from where the mock came probably?

(Get-AllMockBehaviors is probably the right place where to attach the block / test to the behavior, so we can later get the description from that.)

@HeyItsGilbert

Copy link
Copy Markdown
  • and - are already used for the test results, I think it is more confusing.

Yea that makes sense. Plus +/- being pass fail makes more sense that as a signifier in this situation. How about this?

Performed invocations:
  [ ]: $Name-Hello from...
  [*]: $Name-Hello from...

@nohwnd

nohwnd commented Mar 14, 2026

Copy link
Copy Markdown
Member Author

I like that a lot

@nohwnd nohwnd added this to the 6.0.0 milestone Jun 16, 2026
nohwnd and others added 2 commits June 18, 2026 15:45
Refine Format-MockCallHistoryMessage: use [*]/[ ] markers for matching
vs non-matching calls, format parameter values with Format-Nicely2,
handle zero-call case with <none>.

Update Should-Invoke test assertions from exact -Be to -BeLike with
wildcard suffix so they tolerate the appended call history text.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread src/functions/Mock.ps1 Fixed
Comment thread src/functions/Mock.ps1 Fixed
…ryMessage

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@nohwnd nohwnd marked this pull request as ready for review June 23, 2026 09:59
nohwnd and others added 4 commits June 23, 2026 12:31
Test the full failure message including history section for:
- Filter matches 0 out of 3 calls (all [ ])
- Filter matches 1 out of 3 but expected 2 (mix of [*] and [ ])
- All 3 match but expected 4 (all [*])
- Zero calls (shows <none>)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Show file:line of the Mock -MockWith scriptblock in the invocation
history so users can identify which behavior handled each call.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Spell out markers and command names, only wildcard path prefix and
line numbers to avoid brittleness.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@nohwnd nohwnd merged commit f7b374b into main Jun 23, 2026
13 checks passed
@nohwnd nohwnd deleted the mock-history branch June 23, 2026 13:07
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.

3 participants