2017-01-27 2 views
2

Я очень новый приставать, и я пытаюсь построить тесты для очень небольшой и простой функции в PowerShell:Как должна функция Mock принимать вход конвейера в Pester?

function Toggle-Notepad { 
    if (-not (Get-Process notepad -ErrorAction SilentlyContinue)) 
    { 
     Start-Process -FilePath Notepad 
    } 
    else 
    { 
     get-process notepad | stop-process 
    } 

} 

Эта функция только начинает блокнот, если она не работает, иначе, если он работает она останавливается Это.

тест, который я разработал это:

$here = Split-Path -Parent $MyInvocation.MyCommand.Path 
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.', '.' 
. "$here\$sut" 

Describe "Toggle-Notepad" { 
    Mock Stop-Process { "Process object passed! Stopping notepad!" } 
    Mock Start-Process { "Notepad is not running,starting it!" } -ParameterFilter { $Filepath -eq "Notepad" } 

    It "Starts notepad if it is not running" { 
     Toggle-Notepad | Should be "Notepad is not running,starting it!" 
    } 

    It "Stops notepad if it is running" { 
     Toggle-Notepad | Should be "Process object passed ! Stopping notepad!" 
    } 
} 

Вышеуказанные испытания выполняются, как ожидалось.

Как переписать функцию Stop-Process, чтобы я мог указать, что эта версия предназначена для приема ввода конвейера?

Я попытался это, но он не работает:

$here = Split-Path -Parent $MyInvocation.MyCommand.Path 
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.', '.' 
. "$here\$sut" 

Describe "Toggle-Notepad" { 
    Mock stop-process { "Process object passed ! Stopping notepad" } -ParameterFilter { $InputObject -is "System.Diagnostics.Process" } 
    Mock Start-Process {"Notepad is not running,starting it!"} -ParameterFilter { $Filepath -eq "Notepad" } 

    It "Starts notepad if it is not running" { 
     Toggle-Notepad | Should be "Notepad is not running,starting it!" 
    } 

    It "Stops notepad if it is running" { 
     Toggle-Notepad | Should be "Process object passed ! Stopping notepad!" 
    } 
} 

Поскольку функция Stop-Process принимает входные данные из конвейера моя цель заключается в дразнят функцию, аналогичную функции, а не создавать общую Stop-Process функцию, которая не несет Params ,

Есть ли кто-нибудь из экспертов Pester, кто может помочь?

ответ

0

Вы можете издеваться функцию принятия значения трубопровода, как и любой другой функции:

Describe "Toggle-Notepad" { 
    Mock Stop-Process { 
     [CmdletBinding()] 
     param(
      [Parameter(ValueFromPipeline = $true)] 
      $InputObject 
     ) 
     return "Process object passed! Stopping notepad" 
    } -ParameterFilter { $InputObject -is "System.Diagnostics.Process" } 

    Mock Start-Process { 
     return "Notepad is not running, starting it!" 
    } -ParameterFilter { $Filepath -eq "Notepad" } 

    It "Starts notepad if it is not running" { 
     Toggle-Notepad | Should be "Notepad is not running, starting it!" 
    } 

    It "Stops notepad if it is running" { 
     Toggle-Notepad | Should be "Process object passed! Stopping notepad!" 
    } 
} 

Пожалуйста, обратите внимание также, что ваш издевались Stop-Process имеет опечаток в нем, поэтому он не будет работать.

1

Обычно вам не нужно вручную определять параметры в пределах Mock, потому что параметры функции, издевательства, создаются автоматически в макете.

Причина, по которой ваш Stop-Process Mock не работает, потому что вы определили его с свойством -ParamaterFilter, в результате чего он вызывается только при заданном параметре true. Ваш фильтр не работает, потому что вы ссылаетесь на тип объекта как строку ("System.Diagnostics.Process"), а не как тип (который объявлен с квадратными скобками).

Правильный код для Мок является:

Mock stop-process { "Process object passed ! Stopping notepad!" } -ParameterFilter { $InputObject -is [System.Diagnostics.Process[]] } 

Я asked this question of the Pester development team directly и они предложили более простое решение просто -ParameterFilter { $InputObject }, как это будет пустой, если она не заполняется с действительным объектом этого типа.

Вот полный пример:

Describe 'Mocking stop-process' { 

    Mock Stop-Process { 
     Write-Host "Mock stopping: $InputObject" 
    } -ParameterFilter { $InputObject } 

    It 'Should mock stopping the notepad process' { 
     Get-Process notepad | Stop-Process | Should Be $null 
    } 

} 

Также FYI, так как Pester 3.4.4 теперь есть New-MockObject команда, которая позволяет создавать поддельные объекты любого типа:

Нью-MockObject является функцией Pester (введенной в Pester 3.4.4), что позволяет создавать «поддельные» объекты практически любого типа для работы в Pester mocks. Эти «поддельные объекты» позволяют вашим mocks возвращать тот же тип , что и функция, издевательская, чтобы передать результат сущностям , которые строго типизированы.

Это не обязательно в вашем сценарии, но я думал, что вы можете найти его актуальным/интересным.

+0

Высказывание _ «не должно определять барабанщиков [...]» _ не делает другой ответ _incorrect_, особенно если он работает так, как ожидалось. – Clijsters

+0

Да, на самом деле, при отражении вы можете определить дополнительные параметры, которых не было в функции командлета, издевающегося, я думаю, но вы должны быть осторожны, чтобы не переопределять параметры, которые создаются автоматически. Извините, я пересмотрю свой ответ. –