当前位置:网站首页 > 更多 > 玩电脑 > 正文

[玩转系统] 理解 Pester 中的模拟

作者:精品下载站 日期:2024-12-14 20:52:57 浏览:9 分类:玩电脑

理解 Pester 中的模拟


如果您想确保您的 PowerShell 代码处于最佳状态,您需要对其进行单元测试。 Pester 是一个为 PowerShell 代码构建的流行单元测试框架,可让您确保编写的代码符合您的预期并保持这种状态。

在进行单元测试时,必须确保您的代码不会受到其运行环境或任何其他外部函数或模块的任何影响。单元测试将单个单元作为一个整体进行测试,以确保开发人员能够准确地确定单个“单元”的行为是否符合预期。

确保单元测试准确且不受其他代码影响的一种方法是通过称为模拟的概念。模拟是 Pester 中的一项功能,它允许您用您自己的命令“替换”您的“单元”正在调用的命令。模拟使您能够在测试“单元”内设置各种场景命令,以找出在各种情况下可能发生的情况。

如果现在还没有意义,希望一个简短的演示能让灯泡亮起来!为了跟随演示,我希望您对 Pester 测试框架有初级到中级的了解。

如果您想深入研究模拟和许多现实世界的示例,请务必查看 The Pester Book。

模拟演示

假设您有一个 PowerShell 函数,仅当该文件尚不存在时才创建该文件。为此,您首先使用 Test-Path 命令检查该文件是否存在,如果返回 False,则创建该文件。

你的函数看起来像这样:

function New-FictionalFile {
    [CmdletBinding()]
    param(
        [Parameter()]
        [string]$FilePath
    )
    if (-not (Test-Path -Path $FilePath)) {
        $null = New-Item -Path $FilePath -ItemType File
    }
}

此功能的典型 Pester 测试如下所示。我假设上面的函数位于名为 C:\New-FictionalFile.ps1 的脚本中。

下面的测试是为了确保该函数创建该文件(如果该文件尚不存在)。这很棒,但有两个问题;它取决于环境(保存文件的存储),并且不会在文件已经存在时测试场景。

describe 'New-FictionalFile' {
    context 'when the file path does not exist' {
        ## Ensure the test file isn't there
        $null = Remove-Item -Path '~\file.txt' -ErrorAction Ignore
        $null = New-FictionalFile -FilePath '~\file.txt'
        
        it 'creates the file' {
            '~\file.txt' | Should -Exist
        }
    }
}

要构建正确的单元测试,您必须从测试中删除环境要求。当文件已经存在时,您还必须测试该场景。为此,您需要确保未调用 New-Item cmdlet。解决这两个问题的唯一方法就是使用mocking。

您需要模拟或“替换”Test-PathNew-Item cmdlet 的功能,以在不依赖环境的情况下控制它们的输出。

您可以在下面看到确保创建或删除文件的代码(New-ItemRemove-Item)以及添加的模拟代码。由于您现在已经控制了所有命令的输出,因此不再需要依赖环境。现在,这个单元测试可以在任何地方运行,而无需考虑本地文件系统。

describe 'New-FictionalFile' {
    ## This ensures New-Item will never run. It's just being used as a 
    ## flag to test if it attempts to execute
    mock 'New-Item'

    context 'when the file path does not exist' {
        ## This ensures Test-Path always returns $false "mimicking" the file does not exist
        mock 'Test-Path' { $false }
        
        $null = New-FictionalFile -FilePath '~\file.txt'

        it 'creates the file' {
            ## This checks to see if New-Item attempted to run. If so, we know the script did what we expected
            $assMParams = @{
                CommandName = 'New-Item'
                Times = 1
                Exactly = $true
            }
            Assert-MockCalled @assMParams
        }
    }
    
    context 'when the file path already exists' {
        ## This ensures Test-Path always returns $true "mimicking" the file does not exist
        mock 'Test-Path' { $true }

        $null = New-FictionalFile -FilePath '~\file.txt'

        it 'does not attempt to create a file' {
            ## This checks to see if New-Item did not attempt to run (Times = 0). If it did not
            ## that means that it did not attempt to create the file
            $assMParams = @{
                CommandName = 'New-Item'
                Times = 0
                Exactly = $true
            }
            Assert-MockCalled @assMParams
        }
    }
}

要了解有关 Assert-MockCalled 命令的更多信息,请务必查看 Pester 文档。

概括

Pester 中的模拟概念可能会让单元测试新手感到困惑。这是一个强大的功能,可以更好地控制您的代码,并确保测试以相同的方式运行,无论它们所处的环境如何。

如果您想了解有关 Pester 中的嘲笑的更多信息,请查看 The Pester Book。在本书中,您将深入了解模拟工作以及如何将其应用于许多不同的场景。

您需要 登录账户 后才能发表评论

取消回复欢迎 发表评论:

关灯