如何使用Pester模拟匿名高级函数中的函数
How to use Pester to mock functions in anonymous advanced functions
我最近发现我不需要使用 Import-Module 来使用我的高级 powershell 函数,我可以在 ps1 文件中匿名定义一个函数。
不幸的是,我的 Pester 单元测试被破坏了。我似乎无法再在下面的列表中模拟对 New-Object 的调用。通常,我会点源以下代码并在我的范围内定义函数 Get-StockQuote。现在点采购 ps1 文件没有帮助,因为我无论如何都通过文件名调用该函数。
我如何使用 Pester 通过 New-Object 的模拟实现来测试以下代码?
注意:这段代码对于问题的目的来说显然是微不足道的,我正在使用的代码测试确实需要 New-Object 的模拟实现。
# Source listing of the file: Get-StockQuote.ps1
<#
.Synopsis
Looks up a stock quote
.Description
Uses the yahoo api to retrieve a recent quote for a given stock.
.Parameter Symbol
The stock trading symbol
.Example
Get-StockQuote.ps1 -Symbol AMZN
Prints the following line to the output
440.84
#>
[CmdletBinding()]
Param(
[parameter(Mandatory=$false)]
[string]$Symbol
)
BEGIN {
Set-StrictMode -Version 1
}
PROCESS {
(New-Object System.Net.WebClient).DownloadString("http://finance.yahoo.com/d/quotes.csv?s=$Symbol&f=l1")
}
END {
}
所以我找到了一种方法,通过在 BEGIN 块中定义一个与文件名同名的命名函数并从 PROCESS 块中调用它。
[CmdletBinding()]
Param(
[parameter(Mandatory=$false)]
[string]$Symbol
)
BEGIN {
Set-StrictMode -Version 1
Function Get-StockQuote {
[CmdletBinding()]
Param(
[parameter(Mandatory=$false)]
[string]$Symbol
)
BEGIN{}
PROCESS{
(New-Object System.Net.WebClient).DownloadString("http://finance.yahoo.com/d/quotes.csv?s=$Symbol&f=l1")
}
END{}
}
}
PROCESS {
Get-StockQuote @PSBoundParameters
}
END {
}
这样,在 dot sourc 我的 ps1 文件之后,我将在作用域中拥有函数定义,Pester 将开始正常工作。
$here = Split-Path -Parent $MyInvocation.MyCommand.Path
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path).Replace(".Tests.", ".")
. "$here$sut"
Describe "Get a stock quote" {
Mock New-Object {
$retval = [pscustomobject]@{}
Add-Member -InputObject $retval -MemberType ScriptMethod DownloadString {
param( [string] $url )
if ($url -imatch 'AMZN') {
return 500.01
}
return 100.00
}
return $retval
} -ParameterFilter {$TypeName -and ($TypeName -ilike 'System.Net.WebClient') }
Context "when called for AMZN" {
$result = Get-StockQuote -Symbol AMZN
It "Should RETURN 500.01" {
$result | should be 500.01
}
}
Context "when called for anything else" {
$result = Get-StockQuote -Symbol MSFT
It "Should RETURN 100.00" {
$result | should be 100.00
}
}
}
PowerShell 脚本(.ps1 文件)运行 在它们自己的范围内称为脚本范围。所以我认为 Pester 很难模拟它使用的 cmdlet。
在解决方法中,您被迫声明一个函数,该函数可以看到 cmdlet 的模拟版本。
我最近发现我不需要使用 Import-Module 来使用我的高级 powershell 函数,我可以在 ps1 文件中匿名定义一个函数。
不幸的是,我的 Pester 单元测试被破坏了。我似乎无法再在下面的列表中模拟对 New-Object 的调用。通常,我会点源以下代码并在我的范围内定义函数 Get-StockQuote。现在点采购 ps1 文件没有帮助,因为我无论如何都通过文件名调用该函数。
我如何使用 Pester 通过 New-Object 的模拟实现来测试以下代码?
注意:这段代码对于问题的目的来说显然是微不足道的,我正在使用的代码测试确实需要 New-Object 的模拟实现。
# Source listing of the file: Get-StockQuote.ps1
<#
.Synopsis
Looks up a stock quote
.Description
Uses the yahoo api to retrieve a recent quote for a given stock.
.Parameter Symbol
The stock trading symbol
.Example
Get-StockQuote.ps1 -Symbol AMZN
Prints the following line to the output
440.84
#>
[CmdletBinding()]
Param(
[parameter(Mandatory=$false)]
[string]$Symbol
)
BEGIN {
Set-StrictMode -Version 1
}
PROCESS {
(New-Object System.Net.WebClient).DownloadString("http://finance.yahoo.com/d/quotes.csv?s=$Symbol&f=l1")
}
END {
}
所以我找到了一种方法,通过在 BEGIN 块中定义一个与文件名同名的命名函数并从 PROCESS 块中调用它。
[CmdletBinding()]
Param(
[parameter(Mandatory=$false)]
[string]$Symbol
)
BEGIN {
Set-StrictMode -Version 1
Function Get-StockQuote {
[CmdletBinding()]
Param(
[parameter(Mandatory=$false)]
[string]$Symbol
)
BEGIN{}
PROCESS{
(New-Object System.Net.WebClient).DownloadString("http://finance.yahoo.com/d/quotes.csv?s=$Symbol&f=l1")
}
END{}
}
}
PROCESS {
Get-StockQuote @PSBoundParameters
}
END {
}
这样,在 dot sourc 我的 ps1 文件之后,我将在作用域中拥有函数定义,Pester 将开始正常工作。
$here = Split-Path -Parent $MyInvocation.MyCommand.Path
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path).Replace(".Tests.", ".")
. "$here$sut"
Describe "Get a stock quote" {
Mock New-Object {
$retval = [pscustomobject]@{}
Add-Member -InputObject $retval -MemberType ScriptMethod DownloadString {
param( [string] $url )
if ($url -imatch 'AMZN') {
return 500.01
}
return 100.00
}
return $retval
} -ParameterFilter {$TypeName -and ($TypeName -ilike 'System.Net.WebClient') }
Context "when called for AMZN" {
$result = Get-StockQuote -Symbol AMZN
It "Should RETURN 500.01" {
$result | should be 500.01
}
}
Context "when called for anything else" {
$result = Get-StockQuote -Symbol MSFT
It "Should RETURN 100.00" {
$result | should be 100.00
}
}
}
PowerShell 脚本(.ps1 文件)运行 在它们自己的范围内称为脚本范围。所以我认为 Pester 很难模拟它使用的 cmdlet。
在解决方法中,您被迫声明一个函数,该函数可以看到 cmdlet 的模拟版本。