@@ -348,7 +348,7 @@ function Should-InvokeVerifiableInternal {
348348 }
349349
350350 return [Pester.ShouldResult ] @ {
351- Succeeded = $true
351+ Succeeded = $true
352352 }
353353}
354354
@@ -460,7 +460,8 @@ function Should-InvokeInternal {
460460 # $params.ScriptBlock = New-BlockWithoutParameterAliases -Metadata $ContextInfo.Hook.Metadata -Block $params.ScriptBlock
461461 # }
462462
463- if (Test-ParameterFilter @params ) {
463+ $passed , $filterInvocations = Test-ParameterFilter @params
464+ if ($passed ) {
464465 $null = $matchingCalls.Add ($historyEntry )
465466 }
466467 else {
@@ -530,7 +531,7 @@ function Should-InvokeInternal {
530531 }
531532
532533 return [Pester.ShouldResult ] @ {
533- Succeeded = $true
534+ Succeeded = $true
534535 }
535536}
536537
@@ -798,7 +799,7 @@ function Invoke-MockInternal {
798799 switch ($FromBlock ) {
799800 Begin {
800801 $MockCallState [' InputObjects' ] = [System.Collections.Generic.List [object ]]@ ()
801- $MockCallState [' ShouldExecuteOriginalCommand ' ] = $false
802+ $MockCallState [' MatchedNoBehavior ' ] = $false
802803 $MockCallState [' BeginBoundParameters' ] = $BoundParameters.Clone ()
803804 # argument list must not be null, if the bootstrap functions has no parameters
804805 # we get null and need to replace it with empty array to make the splatting work
@@ -816,7 +817,7 @@ function Invoke-MockInternal {
816817 $SessionState = if ($CallerSessionState ) { $CallerSessionState } else { $Hook.SessionState }
817818
818819 # the @() are needed for powerShell3 otherwise it throws CheckAutomationNullInCommandArgumentArray (unless there is any breakpoint defined anywhere, then it works just fine :DDD)
819- $behavior = FindMatchingBehavior - Behaviors @ ($Behaviors ) - BoundParameters $BoundParameters - ArgumentList @ ($ArgumentList ) - SessionState $SessionState - Hook $Hook
820+ $behavior , $failedFilterInvocations = FindMatchingBehavior - Behaviors @ ($Behaviors ) - BoundParameters $BoundParameters - ArgumentList @ ($ArgumentList ) - SessionState $SessionState - Hook $Hook
820821
821822 if ($null -ne $behavior ) {
822823 $call = @ {
@@ -841,7 +842,8 @@ function Invoke-MockInternal {
841842 return
842843 }
843844 else {
844- $MockCallState [' ShouldExecuteOriginalCommand' ] = $true
845+ $MockCallState [' MatchedNoBehavior' ] = $true
846+ $MockCallState [' FailedFilterInvocations' ] = $failedFilterInvocations
845847 if ($null -ne $InputObject ) {
846848 $null = $MockCallState [' InputObjects' ].AddRange(@ ($InputObject ))
847849 }
@@ -851,69 +853,14 @@ function Invoke-MockInternal {
851853 }
852854
853855 End {
854- if ($MockCallState [' ShouldExecuteOriginalCommand ' ]) {
856+ if ($MockCallState [' MatchedNoBehavior ' ]) {
855857 if ($PesterPreference.Debug.WriteDebugMessages.Value ) {
856- Write-PesterDebugMessage - Scope Mock " Invoking the original command ."
858+ Write-PesterDebugMessage - Scope Mock " The mock did not match any filtered behavior, and there was no default behavior. Failing ."
857859 }
858860
859- $MockCallState [ ' BeginBoundParameters ' ] = Reset-ConflictingParameters - BoundParameters $MockCallState [' BeginBoundParameters ' ]
861+ $failedFilterInvocations = $MockCallState [' FailedFilterInvocations ' ]
860862
861- if ($MockCallState [' InputObjects' ].Count -gt 0 ) {
862- $scriptBlock = {
863- param ($Command , $ArgumentList , $BoundParameters , $InputObjects )
864- $InputObjects | & $Command @ArgumentList @BoundParameters
865- }
866- }
867- else {
868- $scriptBlock = {
869- param ($Command , $ArgumentList , $BoundParameters , $InputObjects )
870- & $Command @ArgumentList @BoundParameters
871- }
872- }
873-
874- $SessionState = if ($CallerSessionState ) {
875- $CallerSessionState
876- }
877- else {
878- $Hook.SessionState
879- }
880-
881- Set-ScriptBlockScope - ScriptBlock $scriptBlock - SessionState $SessionState
882-
883- # In order to mock Set-Variable correctly we need to write the variable
884- # two scopes above
885- if (" Set-Variable" -eq $Hook.OriginalCommand.Name ) {
886- if ($PesterPreference.Debug.WriteDebugMessages.Value ) {
887- Write-PesterDebugMessage - Scope Mock " Original command is Set-Variable, patching the call."
888- }
889- if ($MockCallState [' BeginBoundParameters' ].Keys -notcontains " Scope" ) {
890- $MockCallState [' BeginBoundParameters' ].Add( " Scope" , 2 )
891- }
892- # local is the same as scope 0, in that case we also write to scope 2
893- elseif (" Local" , " 0" -contains $MockCallState [' BeginBoundParameters' ].Scope) {
894- $MockCallState [' BeginBoundParameters' ].Scope = 2
895- }
896- elseif ($MockCallState [' BeginBoundParameters' ].Scope -match " \d+" ) {
897- $MockCallState [' BeginBoundParameters' ].Scope = 2 + $matches [0 ]
898- }
899- else {
900- # not sure what the user did, but we won't change it
901- }
902- }
903-
904- if ($null -eq ($MockCallState [' BeginArgumentList' ])) {
905- $arguments = @ ()
906- }
907- else {
908- $arguments = $MockCallState [' BeginArgumentList' ]
909- }
910- if ($PesterPreference.Debug.WriteDebugMessages.Value ) {
911- Write-ScriptBlockInvocationHint - Hint " Mock - Original Command" - ScriptBlock $scriptBlock
912- }
913- & $scriptBlock - Command $Hook.OriginalCommand `
914- - ArgumentList $arguments `
915- - BoundParameters $MockCallState [' BeginBoundParameters' ] `
916- - InputObjects $MockCallState [' InputObjects' ]
863+ throw " The mock for command '$ ( $Hook.CommandName ) ' did not match any filtered behavior, and there was no default behavior.`n Performed ParameterFilter evaluations:`n $ ( $failedFilterInvocations -join ' `n' ) `n "
917864 }
918865 }
919866 }
@@ -980,6 +927,7 @@ function FindMatchingBehavior {
980927 Write-PesterDebugMessage - Scope Mock " Finding behavior to use, one that passes filter or a default:"
981928 }
982929
930+ $failedFilterInvocations = [System.Collections.Generic.List [String ]]@ ()
983931 $foundDefaultBehavior = $false
984932 $defaultBehavior = $null
985933 foreach ($b in $Behaviors ) {
@@ -999,11 +947,15 @@ function FindMatchingBehavior {
999947 SessionState = $Hook.CallerSessionState
1000948 }
1001949
1002- if (Test-ParameterFilter @params ) {
950+ $passed , $filterInvocations = Test-ParameterFilter @params
951+ if ($passed ) {
1003952 if ($PesterPreference.Debug.WriteDebugMessages.Value ) {
1004953 Write-PesterDebugMessage - Scope Mock " { $ ( $b.ScriptBlock ) } passed parameter filter and will be used for the mock call."
1005954 }
1006- return $b
955+ return $b , $null
956+ }
957+ else {
958+ $failedFilterInvocations.AddRange ($filterInvocations )
1007959 }
1008960 }
1009961 }
@@ -1012,13 +964,13 @@ function FindMatchingBehavior {
1012964 if ($PesterPreference.Debug.WriteDebugMessages.Value ) {
1013965 Write-PesterDebugMessage - Scope Mock " { $ ( $defaultBehavior.ScriptBlock ) } is a default behavior and will be used for the mock call."
1014966 }
1015- return $defaultBehavior
967+ return $defaultBehavior , $null
1016968 }
1017969
1018970 if ($PesterPreference.Debug.WriteDebugMessages.Value ) {
1019- Write-PesterDebugMessage - Scope Mock " No parametrized or default behaviors were found filter ."
971+ Write-PesterDebugMessage - Scope Mock " No parametrized or default behaviors were found."
1020972 }
1021- return $null
973+ return $null , $failedFilterInvocations
1022974}
1023975
1024976function LastThat {
@@ -1241,6 +1193,8 @@ function Test-ParameterFilter {
12411193 else { $null }
12421194 }
12431195
1196+ $parameterFilterInvocations = [Collections.Generic.List [string ]]@ ()
1197+
12441198 $result = & $wrapper $parameters
12451199 if ($result ) {
12461200 if ($PesterPreference.Debug.WriteDebugMessages.Value ) {
@@ -1251,8 +1205,15 @@ function Test-ParameterFilter {
12511205 if ($PesterPreference.Debug.WriteDebugMessages.Value ) {
12521206 Write-PesterDebugMessage - Scope Mock - Message " Mock filter returned value '$result ', which is falsy. Filter did not pass."
12531207 }
1208+
1209+ # Filter did not pass, serialize the values and store them in them for future reference in case we don't find any behavior.
1210+ $hasContext = 0 -lt $Context.Count
1211+ $c = $ (if ($hasContext ) { foreach ($p in $Context.GetEnumerator ()) { " $ ( $p.Key ) = $ ( $p.Value ) " } }) -join " , "
1212+ $filterCall = " mock filter: { $scriptBlock } $ ( if ($hasContext ) { " with parameters: $c " } else { " without any parameters" }) "
1213+ $parameterFilterInvocations.Add ($filterCall )
12541214 }
12551215 $result
1216+ , $parameterFilterInvocations
12561217}
12571218
12581219function Get-ContextToDefine {
0 commit comments