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

Add -Because to Should -Invoke and -InvokeVerifiable #2229

Merged
merged 4 commits into from
Oct 2, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
26 changes: 14 additions & 12 deletions src/functions/Mock.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,8 @@ function Should-InvokeVerifiableInternal {
param(
[Parameter(Mandatory)]
$Behaviors,
[switch]$Negate
[switch] $Negate,
[string] $Because
)

$filteredBehaviors = [System.Collections.Generic.List[Object]]@()
Expand All @@ -314,8 +315,8 @@ function Should-InvokeVerifiableInternal {
}

if ($filteredBehaviors.Count -gt 0) {
if ($Negate) { $message = "$([System.Environment]::NewLine)Expected no verifiable mocks to be called, but these were:" }
else { $message = "$([System.Environment]::NewLine)Expected all verifiable mocks to be called, but these were not:" }
if ($Negate) { $message = "$([System.Environment]::NewLine)Expected no verifiable mocks to be called,$(Format-Because $Because) but these were:" }
else { $message = "$([System.Environment]::NewLine)Expected all verifiable mocks to be called,$(Format-Because $Because) but these were not:" }

foreach ($b in $filteredBehaviors) {
$message += "$([System.Environment]::NewLine) Command $($b.CommandName) "
Expand Down Expand Up @@ -343,18 +344,19 @@ function Should-InvokeInternal {
[Parameter(Mandatory = $true)]
[hashtable] $ContextInfo,

[int]$Times = 1,
[int] $Times = 1,

[Parameter(ParameterSetName = 'ParameterFilter')]
[ScriptBlock]$ParameterFilter = { $True },
[ScriptBlock] $ParameterFilter = { $True },

[Parameter(ParameterSetName = 'ExclusiveFilter', Mandatory = $true)]
[scriptblock] $ExclusiveFilter,

[string] $ModuleName,

[switch]$Exactly,
[switch]$Negate,
[switch] $Exactly,
[switch] $Negate,
[string] $Because,

[Parameter(Mandatory)]
[Management.Automation.SessionState] $SessionState,
Expand Down Expand Up @@ -453,33 +455,33 @@ function Should-InvokeInternal {
if ($matchingCalls.Count -eq $Times -and ($Exactly -or !$PSBoundParameters.ContainsKey("Times"))) {
return [PSCustomObject] @{
Succeeded = $false
FailureMessage = "Expected ${commandName}${moduleMessage} not to be called exactly $Times times"
FailureMessage = "Expected ${commandName}${moduleMessage} not to be called exactly $Times times,$(Format-Because $Because) but it was"
}
}
elseif ($matchingCalls.Count -ge $Times -and !$Exactly) {
return [PSCustomObject] @{
Succeeded = $false
FailureMessage = "Expected ${commandName}${moduleMessage} to be called less than $Times times 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"
}
}
}
else {
if ($matchingCalls.Count -ne $Times -and ($Exactly -or ($Times -eq 0))) {
return [PSCustomObject] @{
Succeeded = $false
FailureMessage = "Expected ${commandName}${moduleMessage} to be called $Times times exactly 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"
}
}
elseif ($matchingCalls.Count -lt $Times) {
return [PSCustomObject] @{
Succeeded = $false
FailureMessage = "Expected ${commandName}${moduleMessage} to be called at least $Times times 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"
}
}
elseif ($filterIsExclusive -and $nonMatchingCalls.Count -gt 0) {
return [PSCustomObject] @{
Succeeded = $false
FailureMessage = "Expected ${commandName}${moduleMessage} to only be called with with parameters matching the specified filter, 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"
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/functions/Pester.SessionState.Mock.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -630,7 +630,7 @@ function Assert-VerifiableMock {
Set-ScriptBlockScope -ScriptBlock $sb -SessionState $PSCmdlet.SessionState
& $sb
}
function Should-InvokeVerifiable ([switch]$Negate) {
function Should-InvokeVerifiable ([switch] $Negate, [string] $Because) {
<#
.SYNOPSIS
Checks if any Verifiable Mock has not been invoked. If so, this will throw an exception.
Expand Down Expand Up @@ -662,7 +662,7 @@ function Should-InvokeVerifiable ([switch]$Negate) {
This will not throw an exception because the mock was invoked.
#>
$behaviors = @(Get-VerifiableBehaviors)
Should-InvokeVerifiableInternal -Behaviors $behaviors -Negate:$Negate
Should-InvokeVerifiableInternal @PSBoundParameters -Behaviors $behaviors
}

& $script:SafeCommands['Add-ShouldOperator'] -Name InvokeVerifiable `
Expand Down
93 changes: 84 additions & 9 deletions tst/functions/Mock.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -676,7 +676,7 @@ Describe "When Creating Verifiable Mock that is not called" {
}

Describe "When Creating multiple Verifiable Mocks that are not called" {
It "Should throw and list all commands" {
BeforeAll {
Mock FunctionUnderTest { return "I am a verifiable test" } -Verifiable -ParameterFilter { $param1 -eq "one" }
Mock FunctionUnderTest { return "I am another verifiable test" } -Verifiable -ParameterFilter { $param1 -eq "two" }
Mock FunctionUnderTest { return "I am probably called" } -Verifiable -ParameterFilter { $param1 -eq "three" }
Expand All @@ -688,9 +688,21 @@ Describe "When Creating multiple Verifiable Mocks that are not called" {
catch {
$result = $_
}
}

It "Should throw and list all commands" {
$result.Exception.Message | Should -Be "$([System.Environment]::NewLine)Expected all verifiable mocks to be called, but these were not:$([System.Environment]::NewLine) Command FunctionUnderTest with { `$param1 -eq `"one`" }$([System.Environment]::NewLine) Command FunctionUnderTest with { `$param1 -eq `"two`" }"
}

It 'Should include reason when -Because is used' {
try {
Should -InvokeVerifiable -Because 'of reasons'
}
Catch {
$failure = $_
}
$failure.Exception.Message | Should -Be "$([System.Environment]::NewLine)Expected all verifiable mocks to be called, because of reasons, but these were not:$([System.Environment]::NewLine) Command FunctionUnderTest with { `$param1 -eq `"one`" }$([System.Environment]::NewLine) Command FunctionUnderTest with { `$param1 -eq `"two`" }"
}
}

Describe "When Creating a Verifiable Mock that is called" {
Expand Down Expand Up @@ -721,6 +733,16 @@ Describe "When calling Should -Not -InvokeVerifiable" {
It "Should throw" {
$result.Exception.Message | Should -Be "$([System.Environment]::NewLine)Expected no verifiable mocks to be called, but these were:$([System.Environment]::NewLine) Command FunctionUnderTest with { `$param1 -eq `"one`" }"
}

It 'Should include reason when -Because is used' {
try {
Should -Not -InvokeVerifiable -Because 'of reasons'
}
Catch {
$failure = $_
}
$failure.Exception.Message | Should -Be "$([System.Environment]::NewLine)Expected no verifiable mocks to be called, because of reasons, but these were:$([System.Environment]::NewLine) Command FunctionUnderTest with { `$param1 -eq `"one`" }"
}
}

Context 'Some Verifiable Mocks are called' {
Expand Down Expand Up @@ -777,16 +799,26 @@ 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 -Be 'Expected FunctionUnderTest to be called 0 times exactly, but was called 1 times'
}

It "Should not throw if mock was not called" {
Should -Invoke FunctionUnderTest 0 -ParameterFilter { $param1 -eq "stupid" }
}

It 'Should include reason when -Because is used' {
try {
Should -Invoke FunctionUnderTest 0 -Scope Describe -Because 'of reasons'
}
Catch {
$failure = $_
}
$failure.Exception.Message | Should -Be 'Expected FunctionUnderTest to be called 0 times exactly, because of reasons, but was called 1 times'
}
}

Describe "When Calling Should -Not -Invoke without exactly" {
BeforeEach {
BeforeAll {
Mock FunctionUnderTest {}
FunctionUnderTest "one"

Expand All @@ -799,7 +831,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"
$result.Exception.Message | Should -Be "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 @@ -845,7 +877,20 @@ 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 -Be "Expected FunctionUnderTest to be called less than $Times times, but was called $MockCalls times"
}

It 'Should include reason when -Because is used' {
FunctionUnderTest
FunctionUnderTest

try {
Should -Not -Invoke FunctionUnderTest -Times 1 -Because 'of reasons'
}
Catch {
$failure = $_
}
$failure.Exception.Message | Should -Be 'Expected FunctionUnderTest to be called less than 1 times, because of reasons, but was called 2 times'
}
}

Expand All @@ -864,7 +909,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 -Be "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 @@ -886,12 +931,22 @@ 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"
$result.Exception.Message | Should -Be "Expected FunctionUnderTest not to be called exactly 1 times, but it was"
}

It "Should not throw if mock was not called" {
Should -Not -Invoke FunctionUnderTest -ParameterFilter { $param1 -eq "stupid" }
}

It 'Should include reason when -Because is used' {
try {
Should -Not -Invoke FunctionUnderTest -Exactly -Scope Describe -Because 'of reasons'
}
Catch {
$failure = $_
}
$failure.Exception.Message | Should -Be 'Expected FunctionUnderTest not to be called exactly 1 times, because of reasons, but it was'
}
}

Describe "When Calling Should -Not -Invoke [Times] with exactly" {
Expand Down Expand Up @@ -933,7 +988,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"
$result.Exception.Message | Should -Be "Expected FunctionUnderTest not to be called exactly $Times times, but it was"
}
}

Expand All @@ -947,7 +1002,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 @@ -962,6 +1017,26 @@ Describe "When Calling Should -Invoke without exactly" {
$scriptBlock = { Should -Invoke FunctionUnderTest -ExclusiveFilter { $param1 -eq 'one' } -Scope Describe }
$scriptBlock | Should -Throw '*1 non-matching calls were made*'
}

It 'Should include reason when -Because is used' {
try {
Should -Invoke FunctionUnderTest 4 -Scope Describe -Because 'of reasons'
}
Catch {
$failure = $_
}
$failure.Exception.Message | Should -Be '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' {
try {
Should -Invoke FunctionUnderTest -ExclusiveFilter { $param1 -eq 'one' } -Scope Describe -Because 'of reasons'
}
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'
}
}

Describe "When Calling Should -Not -Invoke -ExclusiveFilter" {
Expand Down