Пустой список в Pester Mock создан из замыкания
Почему следующий код:
function CreateExecutedCommandsLogger(){
param(
[System.Collections.Generic.List[System.String]]$cmdLog
)
"WWWWW=>{0}" -f $cmdLog | Write-Host
return{
param(
[parameter(valuefrompipeline)]$command
)
"XXXXX=>{0}" -f $command | Write-Host
"YYYYY=>{0}" -f $cmdLog | Write-Host
$cmdLog.Add($command)
}.GetNewClosure()
}
$executedCommands = New-Object System.Collections.Generic.List[System.String]
Mock ExecuteSqlCommand (CreateExecutedCommandsLogger $executedCommands)
Результат в ошибке:
RuntimeException: You cannot call a method on a null-valued expression.
at <ScriptBlock>, <No file>: line 7
at <ScriptBlock>, C:\Users\notme\Documents\WindowsPowerShell\Modules\Pester\Functions\Mock.ps1: line 1018
at ExecuteBlock, C:\Users\notme\Documents\WindowsPowerShell\Modules\Pester\Functions\Mock.ps1: line 1022
at Invoke-Mock, C:\Users\notme\Documents\WindowsPowerShell\Modules\Pester\Functions\Mock.ps1: line 868
at <ScriptBlock><Process>, <No file>: line 53
Для справки вывод трассировки дает:
WWWWW=>System.Collections.Generic.List`1[System.String]
XXXXX=>C:\dummy\command.exe -S "blah" -d "blahblah" -i "something.sql"
YYYYY=>
Когда я использую следующее, это работает:
$dummyMock = (CreateExecutedCommandsLogger $executedCommands)
&$dummyMock "blah"
Я предполагаю, что это как-то связано с тем, как выполняется блок скриптов в макете?
1 ответ
Решение
Как вы можете видеть из источника (Get-Command Mock).ScriptBlock
есть одна строка где $MockWith
параметр используется:
$mockWithCopy = [scriptblock]::Create($MockWith.ToString())
Чтобы, $MockWith
фактически это строка, и любое закрытие игнорируется. Скорее всего это сделано потому, что на следующей строке только что созданный скрипт-блок $mockWithCopy
ограниченный некоторым состоянием сеанса, таким образом, вы теряете свое закрытие в любом случае:
Set-ScriptBlockScope -ScriptBlock $mockWithCopy -SessionState $contextInfo.Session
Сначала Пестер делает личную копию блока скрипта, чтобы не повлиять на переданный экземпляр.