Skip to content

Commit

Permalink
Made code more resilient against mocking Get-Command
Browse files Browse the repository at this point in the history
  • Loading branch information
dlwyatt committed Dec 10, 2015
1 parent 9b6753f commit 975011d
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 12 deletions.
2 changes: 1 addition & 1 deletion Functions/Assertions/Should.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ function Parse-ShouldArgs([array] $shouldArgs) {

function Get-TestResult($shouldArgs, $value) {
$assertionMethod = $shouldArgs.AssertionMethod
$command = Get-Command $assertionMethod -CommandType Function -ErrorAction $script:IgnoreErrorPreference
$command = & $SafeCommands['Get-Command'] $assertionMethod -CommandType Function -ErrorAction $script:IgnoreErrorPreference

if ($null -eq $command)
{
Expand Down
2 changes: 1 addition & 1 deletion Functions/It.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ function Get-ParameterDictionary
try
{
& $SafeCommands['Set-Content'] function:\$guid $ScriptBlock
$metadata = [System.Management.Automation.CommandMetadata](Get-Command -Name $guid -CommandType Function)
$metadata = [System.Management.Automation.CommandMetadata](& $SafeCommands['Get-Command'] -Name $guid -CommandType Function)

return $metadata.Parameters
}
Expand Down
10 changes: 5 additions & 5 deletions Functions/Mock.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ about_Mocking
$mock.Alias = "$($mock.OriginalCommand.ModuleName)\$($CommandName)"

$scriptBlock = {
$setAlias = Get-Command -Name Set-Alias -CommandType Cmdlet -Module Microsoft.PowerShell.Utility
$setAlias = & (Pester\SafeGetCommand) -Name Set-Alias -CommandType Cmdlet -Module Microsoft.PowerShell.Utility
& $setAlias -Name $args[0] -Value $args[1] -Scope Script
}

Expand Down Expand Up @@ -720,8 +720,8 @@ function Validate-Command([string]$CommandName, [string]$ModuleName) {
$commandInfo = & $SafeCommands['New-Object'] psobject -Property @{ Command = $null; Scope = '' }

$scriptBlock = {
$getContentCommand = Get-Command Get-Content -Module Microsoft.PowerShell.Management -CommandType Cmdlet
$newObjectCommand = Get-Command New-Object -Module Microsoft.PowerShell.Utility -CommandType Cmdlet
$getContentCommand = & (Pester\SafeGetCommand) Get-Content -Module Microsoft.PowerShell.Management -CommandType Cmdlet
$newObjectCommand = & (Pester\SafeGetCommand) New-Object -Module Microsoft.PowerShell.Utility -CommandType Cmdlet

$command = $ExecutionContext.InvokeCommand.GetCommand($args[0], 'All')
while ($null -ne $command -and $command.CommandType -eq [System.Management.Automation.CommandTypes]::Alias)
Expand Down Expand Up @@ -793,7 +793,7 @@ function MockPrototype {
[string] ${ignore preference} = 'SilentlyContinue'
}

${get Variable Command} = Get-Command -Name Get-Variable -Module Microsoft.PowerShell.Utility -CommandType Cmdlet
${get Variable Command} = & (Pester\SafeGetCommand) -Name Get-Variable -Module Microsoft.PowerShell.Utility -CommandType Cmdlet

[object] ${a r g s} = & ${get Variable Command} -Name args -ValueOnly -Scope Local -ErrorAction ${ignore preference}
if ($null -eq ${a r g s}) { ${a r g s} = @() }
Expand Down Expand Up @@ -1265,7 +1265,7 @@ function Get-DynamicParametersForCmdlet

try
{
$command = Get-Command -Name $CmdletName -CommandType Cmdlet -ErrorAction Stop
$command = & $SafeCommands['Get-Command'] -Name $CmdletName -CommandType Cmdlet -ErrorAction Stop

if (@($command).Count -gt 1)
{
Expand Down
8 changes: 4 additions & 4 deletions Functions/PesterState.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@ function New-PesterState

$script:SafeCommands = @{}

$script:SafeCommands['New-Object'] = Get-Command -Name New-Object -Module Microsoft.PowerShell.Utility -CommandType Cmdlet
$script:SafeCommands['Select-Object'] = Get-Command -Name Select-Object -Module Microsoft.PowerShell.Utility -CommandType Cmdlet
$script:SafeCommands['Export-ModuleMember'] = Get-Command -Name Export-ModuleMember -Module Microsoft.PowerShell.Core -CommandType Cmdlet
$script:SafeCommands['Add-Member'] = Get-Command -Name Add-Member -Module Microsoft.PowerShell.Utility -CommandType Cmdlet
$script:SafeCommands['New-Object'] = & (Pester\SafeGetCommand) -Name New-Object -Module Microsoft.PowerShell.Utility -CommandType Cmdlet
$script:SafeCommands['Select-Object'] = & (Pester\SafeGetCommand) -Name Select-Object -Module Microsoft.PowerShell.Utility -CommandType Cmdlet
$script:SafeCommands['Export-ModuleMember'] = & (Pester\SafeGetCommand) -Name Export-ModuleMember -Module Microsoft.PowerShell.Core -CommandType Cmdlet
$script:SafeCommands['Add-Member'] = & (Pester\SafeGetCommand) -Name Add-Member -Module Microsoft.PowerShell.Utility -CommandType Cmdlet

function EnterDescribe([string]$Name)
{
Expand Down
3 changes: 2 additions & 1 deletion Pester.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ FunctionsToExport = @(
'AfterAll'
'Get-MockDynamicParameters',
'Set-DynamicParameterVariables',
'Set-TestInconclusive'
'Set-TestInconclusive',
'SafeGetCommand'
)

# # Cmdlets to export from this module
Expand Down
16 changes: 16 additions & 0 deletions Pester.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ else
$outNullModule = 'Microsoft.PowerShell.Utility'
}

# Tried using $ExecutionState.InvokeCommand.GetCmdlet() here, but it does not trigger module auto-loading the way
# Get-Command does. Since this is at import time, before any mocks have been defined, that's probably acceptable.
# If someone monkeys with Get-Command before they import Pester, they may break something.

$script:SafeCommands = @{
'Add-Member' = Get-Command -Name Add-Member -Module Microsoft.PowerShell.Utility -CommandType Cmdlet -ErrorAction Stop
'Add-Type' = Get-Command -Name Add-Type -Module Microsoft.PowerShell.Utility -CommandType Cmdlet -ErrorAction Stop
Expand All @@ -21,6 +25,7 @@ $script:SafeCommands = @{
'ForEach-Object' = Get-Command -Name ForEach-Object -Module Microsoft.PowerShell.Core -CommandType Cmdlet -ErrorAction Stop
'Format-Table' = Get-Command -Name Format-Table -Module Microsoft.PowerShell.Utility -CommandType Cmdlet -ErrorAction Stop
'Get-ChildItem' = Get-Command -Name Get-ChildItem -Module Microsoft.PowerShell.Management -CommandType Cmdlet -ErrorAction Stop
'Get-Command' = Get-Command -Name Get-Command -Module Microsoft.PowerShell.Core -CommandType Cmdlet -ErrorAction Stop
'Get-Content' = Get-Command -Name Get-Content -Module Microsoft.PowerShell.Management -CommandType Cmdlet -ErrorAction Stop
'Get-Date' = Get-Command -Name Get-Date -Module Microsoft.PowerShell.Utility -CommandType Cmdlet -ErrorAction Stop
'Get-Item' = Get-Command -Name Get-Item -Module Microsoft.PowerShell.Management -CommandType Cmdlet -ErrorAction Stop
Expand Down Expand Up @@ -434,6 +439,16 @@ function Get-ScriptBlockScope
[scriptblock].GetProperty('SessionStateInternal', $flags).GetValue($ScriptBlock, $null)
}

function SafeGetCommand
{
<#
.SYNOPSIS
This command is used by Pester's Mocking framework. You do not need to call it directly.
#>

return $script:SafeCommands['Get-Command']
}

$snippetsDirectoryPath = "$PSScriptRoot\Snippets"
if ((& $script:SafeCommands['Test-Path'] -Path Variable:\psise) -and
($null -ne $psISE) -and
Expand All @@ -447,3 +462,4 @@ if ((& $script:SafeCommands['Test-Path'] -Path Variable:\psise) -and
& $script:SafeCommands['Export-ModuleMember'] New-Fixture, Get-TestDriveItem, Should, Invoke-Pester, Setup, InModuleScope, Invoke-Mock
& $script:SafeCommands['Export-ModuleMember'] BeforeEach, AfterEach, BeforeAll, AfterAll
& $script:SafeCommands['Export-ModuleMember'] Get-MockDynamicParameters, Set-DynamicParameterVariables
& $script:SafeCommands['Export-ModuleMember'] SafeGetCommand

0 comments on commit 975011d

Please sign in to comment.