Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 43 additions & 5 deletions src/functions/Mock.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,7 @@ function Should-InvokeInternal {
if ($matchingCalls.Count -eq $Times -and ($Exactly -or !$PSBoundParameters.ContainsKey('Times'))) {
return [Pester.ShouldResult] @{
Succeeded = $false
FailureMessage = "Expected ${commandName}${moduleMessage} not to be called exactly $Times times,$(Format-Because $Because) but it was"
FailureMessage = "Expected ${commandName}${moduleMessage} not to be called exactly $Times times,$(Format-Because $Because) but it was`n$(Format-MockCallHistoryMessage $callHistory $matchingCalls $nonMatchingCalls)"
ExpectResult = [Pester.ShouldExpectResult]@{
Expected = "${commandName}${moduleMessage} not to be called exactly $Times times"
Actual = "${commandName}${moduleMessage} was called $($matchingCalls.count) times"
Expand All @@ -486,7 +486,7 @@ function Should-InvokeInternal {
elseif ($matchingCalls.Count -ge $Times -and !$Exactly) {
return [Pester.ShouldResult] @{
Succeeded = $false
FailureMessage = "Expected ${commandName}${moduleMessage} to be called less than $Times times,$(Format-Because $Because) but was called $($matchingCalls.Count) times"
FailureMessage = "Expected ${commandName}${moduleMessage} to be called less than $Times times,$(Format-Because $Because) but was called $($matchingCalls.Count) times`n$(Format-MockCallHistoryMessage $callHistory $matchingCalls $nonMatchingCalls)"
ExpectResult = [Pester.ShouldExpectResult]@{
Expected = "${commandName}${moduleMessage} to be called less than $Times times"
Actual = "${commandName}${moduleMessage} was called $($matchingCalls.count) times"
Expand All @@ -499,7 +499,7 @@ function Should-InvokeInternal {
if ($matchingCalls.Count -ne $Times -and ($Exactly -or ($Times -eq 0))) {
return [Pester.ShouldResult] @{
Succeeded = $false
FailureMessage = "Expected ${commandName}${moduleMessage} to be called $Times times exactly,$(Format-Because $Because) but was called $($matchingCalls.Count) times"
FailureMessage = "Expected ${commandName}${moduleMessage} to be called $Times times exactly,$(Format-Because $Because) but was called $($matchingCalls.Count) times`n$(Format-MockCallHistoryMessage $callHistory $matchingCalls $nonMatchingCalls)"
ExpectResult = [Pester.ShouldExpectResult]@{
Expected = "${commandName}${moduleMessage} to be called $Times times exactly"
Actual = "${commandName}${moduleMessage} was called $($matchingCalls.count) times"
Expand All @@ -510,7 +510,7 @@ function Should-InvokeInternal {
elseif ($matchingCalls.Count -lt $Times) {
return [Pester.ShouldResult] @{
Succeeded = $false
FailureMessage = "Expected ${commandName}${moduleMessage} to be called at least $Times times,$(Format-Because $Because) but was called $($matchingCalls.Count) times"
FailureMessage = "Expected ${commandName}${moduleMessage} to be called at least $Times times,$(Format-Because $Because) but was called $($matchingCalls.Count) times`n$(Format-MockCallHistoryMessage $callHistory $matchingCalls $nonMatchingCalls)"
ExpectResult = [Pester.ShouldExpectResult]@{
Expected = "${commandName}${moduleMessage} to be called at least $Times times"
Actual = "${commandName}${moduleMessage} was called $($matchingCalls.count) times"
Expand All @@ -521,7 +521,7 @@ function Should-InvokeInternal {
elseif ($filterIsExclusive -and $nonMatchingCalls.Count -gt 0) {
return [Pester.ShouldResult] @{
Succeeded = $false
FailureMessage = "Expected ${commandName}${moduleMessage} to only be called with with parameters matching the specified filter,$(Format-Because $Because) but $($nonMatchingCalls.Count) non-matching calls were made"
FailureMessage = "Expected ${commandName}${moduleMessage} to only be called with with parameters matching the specified filter,$(Format-Because $Because) but $($nonMatchingCalls.Count) non-matching calls were made`n$(Format-MockCallHistoryMessage $callHistory $matchingCalls $nonMatchingCalls)"
ExpectResult = [Pester.ShouldExpectResult]@{
Expected = "${commandName}${moduleMessage} to only be called with with parameters matching the specified filter"
Actual = "${commandName}${moduleMessage} was called $($nonMatchingCalls.Count) times with non-matching parameters"
Expand Down Expand Up @@ -1935,3 +1935,41 @@ function Repair-EnumParameters {

$sb.ToString()
}

function Format-MockCallHistoryMessage ($callHistory, $matchingCalls, $nonMatchingCalls) {
if ($null -eq $callHistory -or $callHistory.Count -eq 0) {
return "Performed invocations:`n <none>"
}

$result = "Performed invocations:"
foreach ($historyEntry in $callHistory) {
$params = $historyEntry.BoundParams
if ($null -ne $params -and $params.Count -gt 0) {
$parts = foreach ($p in $params.GetEnumerator()) { "-$($p.Key) $(Format-Nicely2 $p.Value)" }
$paramText = $parts -join " "
}
else {
$paramText = ""
}

$marker = if ($historyEntry -in $matchingCalls) { "[*]" } else { "[ ]" }
$cmd = $historyEntry.Behavior.CommandName

$location = ""
$sb = $historyEntry.Behavior.ScriptBlock
if ($null -ne $sb -and $sb.File) {
$file = $sb.File
$line = $sb.StartPosition.StartLine
$location = " from ${file}:${line}"
}

if ($paramText) {
$result += "`n $marker $cmd $paramText$location"
}
else {
$result += "`n $marker $cmd$location"
}
}

$result
}
103 changes: 90 additions & 13 deletions tst/functions/Mock.Tests.ps1
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Set-StrictMode -Version Latest
Set-StrictMode -Version Latest
BeforeAll {
$PSDefaultParameterValues = @{ 'Should:ErrorAction' = 'Stop' }
function FunctionUnderTest {
Expand Down Expand Up @@ -743,7 +743,7 @@ Describe "When Calling Should -Invoke 0 without exactly" {
}

It "Should throw if mock was called" {
$result.Exception.Message | Should -Be 'Expected FunctionUnderTest to be called 0 times exactly, but was called 1 times'
$result.Exception.Message | Should -BeLike 'Expected FunctionUnderTest to be called 0 times exactly, but was called 1 times*'
}

It "Should not throw if mock was not called" {
Expand All @@ -757,7 +757,7 @@ Describe "When Calling Should -Invoke 0 without exactly" {
Catch {
$failure = $_
}
$failure.Exception.Message | Should -Be 'Expected FunctionUnderTest to be called 0 times exactly, because of reasons, but was called 1 times'
$failure.Exception.Message | Should -BeLike 'Expected FunctionUnderTest to be called 0 times exactly, because of reasons, but was called 1 times*'
}
}

Expand All @@ -775,7 +775,7 @@ Describe "When Calling Should -Not -Invoke without exactly" {
}

It "Should throw if mock was called once" {
$result.Exception.Message | Should -Be "Expected FunctionUnderTest not to be called exactly 1 times, but it was"
$result.Exception.Message | Should -BeLike "Expected FunctionUnderTest not to be called exactly 1 times, but it was*"
}

It "Should not throw if mock was not called" {
Expand Down Expand Up @@ -817,7 +817,7 @@ Describe "When Calling Should -Not -Invoke [Times] without exactly" {
$result = $_
}

$result.Exception.Message | Should -Be "Expected FunctionUnderTest to be called less than $Times times, but was called $MockCalls times"
$result.Exception.Message | Should -BeLike "Expected FunctionUnderTest to be called less than $Times times, but was called $MockCalls times*"
}

It 'Should include reason when -Because is used' {
Expand All @@ -830,7 +830,7 @@ Describe "When Calling Should -Not -Invoke [Times] without exactly" {
Catch {
$failure = $_
}
$failure.Exception.Message | Should -Be 'Expected FunctionUnderTest to be called less than 1 times, because of reasons, but was called 2 times'
$failure.Exception.Message | Should -BeLike 'Expected FunctionUnderTest to be called less than 1 times, because of reasons, but was called 2 times*'
}
}

Expand All @@ -849,7 +849,7 @@ Describe "When Calling Should -Invoke with exactly" {
}

It "Should throw if mock was not called the number of times specified" {
$result.Exception.Message | Should -Be "Expected FunctionUnderTest to be called 3 times exactly, but was called 2 times"
$result.Exception.Message | Should -BeLike "Expected FunctionUnderTest to be called 3 times exactly, but was called 2 times*"
}

It "Should not throw if mock was called the number of times specified" {
Expand All @@ -871,7 +871,7 @@ Describe "When Calling Should -Not -Invoke with exactly" {
}

It "Should throw if mock was called" {
$result.Exception.Message | Should -Be "Expected FunctionUnderTest not to be called exactly 1 times, but it was"
$result.Exception.Message | Should -BeLike "Expected FunctionUnderTest not to be called exactly 1 times, but it was*"
}

It "Should not throw if mock was not called" {
Expand All @@ -885,7 +885,7 @@ Describe "When Calling Should -Not -Invoke with exactly" {
Catch {
$failure = $_
}
$failure.Exception.Message | Should -Be 'Expected FunctionUnderTest not to be called exactly 1 times, because of reasons, but it was'
$failure.Exception.Message | Should -BeLike 'Expected FunctionUnderTest not to be called exactly 1 times, because of reasons, but it was*'
}
}

Expand Down Expand Up @@ -924,7 +924,7 @@ Describe "When Calling Should -Not -Invoke [Times] with exactly" {
$result = $_
}

$result.Exception.Message | Should -Be "Expected FunctionUnderTest not to be called exactly $Times times, but it was"
$result.Exception.Message | Should -BeLike "Expected FunctionUnderTest not to be called exactly $Times times, but it was*"
}
}

Expand All @@ -938,7 +938,7 @@ Describe "When Calling Should -Invoke without exactly" {

It "Should throw if mock was not called at least the number of times specified" {
$scriptBlock = { Should -Invoke FunctionUnderTest 4 -Scope Describe }
$scriptBlock | Should -Throw "Expected FunctionUnderTest to be called at least 4 times, but was called 3 times"
$scriptBlock | Should -Throw "Expected FunctionUnderTest to be called at least 4 times, but was called 3 times*"
}

It "Should not throw if mock was called at least the number of times specified" {
Expand All @@ -961,7 +961,7 @@ Describe "When Calling Should -Invoke without exactly" {
Catch {
$failure = $_
}
$failure.Exception.Message | Should -Be 'Expected FunctionUnderTest to be called at least 4 times, because of reasons, but was called 3 times'
$failure.Exception.Message | Should -BeLike 'Expected FunctionUnderTest to be called at least 4 times, because of reasons, but was called 3 times*'
}

It 'Should include reason when -Because is used with -ExclusiveFilter' {
Expand All @@ -971,7 +971,84 @@ Describe "When Calling Should -Invoke without exactly" {
Catch {
$failure = $_
}
$failure.Exception.Message | Should -Be 'Expected FunctionUnderTest to only be called with with parameters matching the specified filter, because of reasons, but 1 non-matching calls were made'
$failure.Exception.Message | Should -BeLike 'Expected FunctionUnderTest to only be called with with parameters matching the specified filter, because of reasons, but 1 non-matching calls were made*'
}
}

Describe "Mock call history in Should -Invoke failure messages" {
It "Shows all calls as non-matching when filter matches 0 out of 3" {
Mock FunctionUnderTest { }
FunctionUnderTest "one"
FunctionUnderTest "two"
FunctionUnderTest "three"

try {
Should -Invoke FunctionUnderTest -ParameterFilter { $param1 -eq 'four' }
}
catch {
$failure = $_
}

$failure.Exception.Message | Should -BeLike ("Expected FunctionUnderTest*was called 0 times
Performed invocations:
[[] ] FunctionUnderTest -param1 'one' from *Mock.Tests.ps1:*
[[] ] FunctionUnderTest -param1 'two' from *Mock.Tests.ps1:*
[[] ] FunctionUnderTest -param1 'three' from *Mock.Tests.ps1:*" -replace "`r`n", "`n")
}

It "Shows matching and non-matching calls when filter matches 1 out of 3 but expected 2" {
Mock FunctionUnderTest { }
FunctionUnderTest "one"
FunctionUnderTest "two"
FunctionUnderTest "one"

try {
Should -Invoke FunctionUnderTest -Exactly 2 -ParameterFilter { $param1 -eq 'two' }
}
catch {
$failure = $_
}

$failure.Exception.Message | Should -BeLike ("Expected FunctionUnderTest*was called 1 times*
Performed invocations:
[[] ] FunctionUnderTest -param1 'one' from *Mock.Tests.ps1:*
[[]*] FunctionUnderTest -param1 'two' from *Mock.Tests.ps1:*
[[] ] FunctionUnderTest -param1 'one' from *Mock.Tests.ps1:*" -replace "`r`n", "`n")
}

It "Shows all calls as matching when all 3 match but expected 4" {
Mock FunctionUnderTest { }
FunctionUnderTest "one"
FunctionUnderTest "one"
FunctionUnderTest "one"

try {
Should -Invoke FunctionUnderTest -Exactly 4 -ParameterFilter { $param1 -eq 'one' }
}
catch {
$failure = $_
}

$failure.Exception.Message | Should -BeLike ("Expected FunctionUnderTest*was called 3 times*
Performed invocations:
[[]*] FunctionUnderTest -param1 'one' from *Mock.Tests.ps1:*
[[]*] FunctionUnderTest -param1 'one' from *Mock.Tests.ps1:*
[[]*] FunctionUnderTest -param1 'one' from *Mock.Tests.ps1:*" -replace "`r`n", "`n")
}

It 'Shows empty marker when mock was never called' {
Mock FunctionUnderTest { }

try {
Should -Invoke FunctionUnderTest -Exactly 1
}
catch {
$failure = $_
}

$failure.Exception.Message | Should -Be ('Expected FunctionUnderTest to be called 1 times exactly, but was called 0 times
Performed invocations:
<none>' -replace "`r`n", "`n")
}
}

Expand Down
Loading