gpt4 book ai didi

unit-testing - 在 .ps1 脚本中模拟函数

转载 作者:行者123 更新时间:2023-12-02 23:03:10 25 4
gpt4 key购买 nike

我有一个 PowerShell .ps1 文件,其中包含脚本顶部的函数,后跟调用这些函数的不同命令。我正在使用 Pester 对我的脚本文件进行单元测试。

如何模拟 PowerShell .ps1 脚本中的函数?

我尝试模拟该函数,但收到错误消息“无法找到命令”。

我还尝试在描述 block 中添加一个空的“虚拟”函数。这不会给我上述错误,但它没有正确模拟脚本中的函数。

我有两个文件。一个用于保存测试,另一个用于保存函数和对函数的调用。下面是两个例子:

文件1.ps1

Function Backup-Directory([switch]$IsError)
{
If($IsError)
{
Write-Error "Error"
Exit 1
}
}

Backup-Directory $true

文件2.Tests.ps1

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

Describe "File1" {

Context "When the Back-Directory outputs an error." {

# Arrange
Mock Back-Directory { }
Mock Write-Error

# Act
& $productionFile
$hasSucceeded = $?

# Assert
It "Calls Backup-Directory" {
Assert-MockCalled Backup-Directory -Exactly 1 -ParameterFilter {
$IsError -eq $true
}
}

It "Writes error message." {
Assert-MockCalled Write-Error -Exactly 1 -ParameterFilter {
$Message -eq "Error"
}
}

It "Exits with an error." {
$hasSucceeded | Should be $false
}
}
}

最佳答案

我认为这是不可能的。至少在您当前的实现中是这样。我不久前问过同样的问题... Pester Issue 414

但是您可以将该内部函数拆分到同一目录中的另一个脚本文件中,以便您可以对其进行单元测试和模拟。您只需在主脚本文件中点源该函数即可使用它:

主函数.ps1:

# Main script
function Main-Function {
# if debugging, set moduleRoot to current directory
if ($MyInvocation.MyCommand.Path) {
$moduleRoot = Split-Path -Path $MyInvocation.MyCommand.Path
}else {
$moduleRoot = $PWD.Path
}

# dot source the inner function
. "$moduleRoot\Inner-Function.ps1"

Write-Output "This is the main script. Calling the inner function"

Inner-Function

Write-Output "Back in the main script"
}

内部函数.ps1:

function Inner-Function {
Write-Output "This is the inner function"
}

Main-Function.Tests.ps1:

$moduleRoot =  Split-Path -Parent $MyInvocation.MyCommand.Path 

# Load Testing Function
. "$moduleRoot\Main-Function.ps1"

# Load Supporting Functions
. "$moduleRoot\Inner-Function.ps1"

Describe 'Main Script' {
Mock Inner-Function { return "This is a mocked function" }

It 'uses the mocked function' {
(Main-Function -match "This is a mocked function") | Should Be $true
}
}

这是一个非常好的方法,因为我们可以对内部函数进行单元测试,并且随着逻辑的增长,向其添加测试非常容易(并且可以与其余脚本/函数隔离地完成)。

内部函数.Tests.ps1:

$moduleRoot =  Split-Path -Parent $MyInvocation.MyCommand.Path 

# Load Testing Function
. "$moduleRoot\Inner-Function.ps1"

Describe 'Inner Function' {
It 'outputs some text' {
Inner-Function | Should Be "This is the inner function"
}
}

这里有两个要点......

无论当前执行目录如何,都查找依赖函数位置...

if ($MyInvocation.MyCommand.Path) {
$moduleRoot = Split-Path -Path $MyInvocation.MyCommand.Path
}else {
$moduleRoot = $PWD.Path
}

并且

点源取决于主函数中的函数以及单元测试文件... 。 “$moduleRoot\Inner-Function.ps1”

Split-Path -Path $MyInitation.MyCommand.Path 在用户 session 中为 $null,但在以下情况下不会为 $null从执行上下文中调用。这意味着,您可以在 C:\users\nhudacin 中仍然正确加载此脚本/模块。否则,您必须始终在其所在的同一目录中执行此脚本/模块,而不使用 $MyInvoation 变量。

关于unit-testing - 在 .ps1 脚本中模拟函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37278503/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com