如何从另一个脚本嘲笑pscustomobject的脚本?

发布于 2025-01-17 13:05:32 字数 1521 浏览 4 评论 0原文

我们正在尝试弄清楚如何使用Pester从另一个脚本嘲笑PscustomObject的脚本。

script1.ps1

$script2    = & $Script2PS1Path -programName $myScriptName

function Invoke-MyFunction {

$script2.outHost("test data")

Get-ChildItem -Directory -Path $path -Filter "ABC_*"
...
...
}

script2.ps1

param (
    [Parameter(Mandatory=$True,ValueFromPipeline=$False,HelpMessage="Mandatory.")]
    [string]$programName
)

$ErrorActionPreference = "Stop"

$obj = New-Object PSCustomObject
$obj | Add-Member -MemberType NoteProperty -name prog               -Value $programName
$obj | Add-Member -MemberType ScriptMethod -name outHost -Value {
    param (
        [Parameter(Mandatory=$True,ValueFromPipeline=$True)]
        $text,

        [Parameter(Mandatory=$False,ValueFromPipeline=$True)]
        [string]$foregroundcolor,

        [Parameter(Mandatory=$False,ValueFromPipeline=$True)]
        [string]$backgroundcolor
    )

    if ($foregroundcolor -and $backgroundcolor) {
        Write-Host -Foregroundcolor $foregroundcolor -Backgroundcolor $backgroundcolor $text
    } elseif ($foregroundcolor) {
        Write-Host -Foregroundcolor $foregroundcolor $text
    } elseif ($backgroundcolor) {
        Write-Host -Backgroundcolor $backgroundcolor $text
    } else {
        Write-Host $text
    }
}

$obj

exit(0)

在上面的示例中,我们需要模拟$ script2.uthost test Indoke-myfunction。模拟$ script2.outhost的最佳方法是什么?

We are trying to figure out how to mock a ScriptMethod of PSCustomObject from another script using Pester.

Script1.ps1

$script2    = & $Script2PS1Path -programName $myScriptName

function Invoke-MyFunction {

$script2.outHost("test data")

Get-ChildItem -Directory -Path $path -Filter "ABC_*"
...
...
}

Script2.ps1

param (
    [Parameter(Mandatory=$True,ValueFromPipeline=$False,HelpMessage="Mandatory.")]
    [string]$programName
)

$ErrorActionPreference = "Stop"

$obj = New-Object PSCustomObject
$obj | Add-Member -MemberType NoteProperty -name prog               -Value $programName
$obj | Add-Member -MemberType ScriptMethod -name outHost -Value {
    param (
        [Parameter(Mandatory=$True,ValueFromPipeline=$True)]
        $text,

        [Parameter(Mandatory=$False,ValueFromPipeline=$True)]
        [string]$foregroundcolor,

        [Parameter(Mandatory=$False,ValueFromPipeline=$True)]
        [string]$backgroundcolor
    )

    if ($foregroundcolor -and $backgroundcolor) {
        Write-Host -Foregroundcolor $foregroundcolor -Backgroundcolor $backgroundcolor $text
    } elseif ($foregroundcolor) {
        Write-Host -Foregroundcolor $foregroundcolor $text
    } elseif ($backgroundcolor) {
        Write-Host -Backgroundcolor $backgroundcolor $text
    } else {
        Write-Host $text
    }
}

$obj

exit(0)

In the example above we need to mock $script2.outHost to test Invoke-MyFunction. What is the best way to mock $script2.outHost ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

像极了他 2025-01-24 13:05:32

这实际上取决于您如何在测试中调用它 +这确实是脚本而不是模块(增加了一些复杂性)。

如果script1.ps1beforeall -block中点缀,然后您在iT-block中运行Invoke-myfunction,然后只需覆盖scriptMethod如评论中提到的,例如。

It 'myTest' {
    $script2 | Add-Member -Force -MemberType ScriptMethod -name outHost -Value { 'mocked behavior' }`
    Invoke-MyFunction
}

如果script1.ps1确实在脚本内注入Indoke-myfunction,因此您的测试仅执行& script1.ps1,然后您必须模拟add-member,并使用-parameterFilter来定位正确的调用。例如:

script1.ps1

# Temp variables to make sample complete
# Script2.ps1 from OP is placed in the same folder
$Script2PS1Path = "$PSScriptRoot\Script2.ps1"
$myScriptName = 'demo'

$script2 = & $Script2PS1Path -programName $myScriptName

function Invoke-MyFunction {
    $script2.outHost('test data')
}

# Added to complete sample
Invoke-MyFunction

script1.tests.ps1

Describe 'Script1' {
    It 'mockoutHost' {
        # Create mock for Add-Member targeted for the outHost-call
        Mock -CommandName Add-Member -ParameterFilter { $MemberType -eq 'ScriptMethod' -and $Name -eq 'outHost' } -MockWith {
            # Get real Add-Member
            $cmd = (Get-Command -Name Add-Member -CommandType Cmdlet)

            # Override incoming Value (ScriptMethod-codeblock)
            # $PesterBoundParameters requires Pester 5.2+
            $PesterBoundParameters['Value'] = { Write-Warning "I got mocked at $((Get-Date).ToString('o'))" }

            # Call real Add-Member with modified ScriptMethod
            & $cmd @PesterBoundParameters
        }

        # Invoke Script1.ps1
        & "$PSScriptRoot\Script1.ps1"
        # Profit
    }
}

输出:

Starting discovery in 1 files.
Discovery found 1 tests in 24ms.
Running tests.
WARNING: I got mocked at 2022-08-03T21:57:04.4306325+00:00
[+] /workspaces/Pester/Samples/MockScriptMethod/Script1.Tests.ps1 100ms (52ms|25ms)
Tests completed in 101ms
Tests Passed: 1, Failed: 0, Skipped: 0 NotRun: 0

It really depends on how you invoke this in your tests + that this is really scripts and not modules (adds some complexity).

If Script1.ps1 is dot-sourced in a BeforeAll-block and you run Invoke-MyFunction in the It-block, then simply override the ScriptMethod as mentioned in the comments, ex.

It 'myTest' {
    $script2 | Add-Member -Force -MemberType ScriptMethod -name outHost -Value { 'mocked behavior' }`
    Invoke-MyFunction
}

If Script1.ps1 really invokes Invoke-MyFunction inside the script, so your test only execute & Script1.ps1, then you'd have to mock Add-Member and target the right call using -ParameterFilter. Ex:

Script1.ps1

# Temp variables to make sample complete
# Script2.ps1 from OP is placed in the same folder
$Script2PS1Path = "$PSScriptRoot\Script2.ps1"
$myScriptName = 'demo'

$script2 = & $Script2PS1Path -programName $myScriptName

function Invoke-MyFunction {
    $script2.outHost('test data')
}

# Added to complete sample
Invoke-MyFunction

Script1.tests.ps1

Describe 'Script1' {
    It 'mockoutHost' {
        # Create mock for Add-Member targeted for the outHost-call
        Mock -CommandName Add-Member -ParameterFilter { $MemberType -eq 'ScriptMethod' -and $Name -eq 'outHost' } -MockWith {
            # Get real Add-Member
            $cmd = (Get-Command -Name Add-Member -CommandType Cmdlet)

            # Override incoming Value (ScriptMethod-codeblock)
            # $PesterBoundParameters requires Pester 5.2+
            $PesterBoundParameters['Value'] = { Write-Warning "I got mocked at $((Get-Date).ToString('o'))" }

            # Call real Add-Member with modified ScriptMethod
            & $cmd @PesterBoundParameters
        }

        # Invoke Script1.ps1
        & "$PSScriptRoot\Script1.ps1"
        # Profit
    }
}

Output:

Starting discovery in 1 files.
Discovery found 1 tests in 24ms.
Running tests.
WARNING: I got mocked at 2022-08-03T21:57:04.4306325+00:00
[+] /workspaces/Pester/Samples/MockScriptMethod/Script1.Tests.ps1 100ms (52ms|25ms)
Tests completed in 101ms
Tests Passed: 1, Failed: 0, Skipped: 0 NotRun: 0
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文