Как вы пишете макет Пестера для установки переменной последовательности задач - PullRequest
1 голос
/ 29 апреля 2020

Я работаю над написанием тестов Пестера для наших скриптов PowerShell, которые используются во время последовательностей задач. Некоторые из них работают с переменными последовательности задач, и поэтому я написал макет, который позволяет тестировать переменные чтения, и сейчас пытаюсь выяснить, как это сделать для записи переменных. Это код для чтения переменной последовательности задач:

$TsEnv = New-Object -COMObject Microsoft.SMS.TSEnvironment
$Value = $TsEnv.Value('VariableNameToRead')

Передав функцию $TsEnv в функцию, я могу затем посмеяться над ней следующим образом:

$TsEnv = @{
    'VariableNameToRead' = 'TestValue'
}
Add-Member -InputObject $TsEnv -MemberType ScriptMethod -Name Value -Value {
    Param( [String]$Key )
    $This[$Key]
} 

Это код для написания переменной последовательности задач:

$TsEnv = New-Object -COMObject Microsoft.SMS.TSEnvironment
$TsEnv.Value('VariableNameToWrite') = 'ValueToWrite'

Когда он находится в скобках после $TsEnv.Value Я думаю, что это трактуется как метод, но я не могу найти примеров того, как присваивать значения методу.

Ответы [ 2 ]

0 голосов
/ 03 мая 2020

Что-нибудь, чтобы иметь дело с получением переменных окружения, WMI или с помощью tnet stati c вызовов методов, я хотел бы содержать в небольшой вспомогательной функции, тогда ее очень легко смоделировать. Вот как может выглядеть этот помощник.

Function Get-SMSTsVariable{($VariableName)
    return $TSEnv.Value($VariableName)
}

Затем вы можете легко смоделировать это в различных контекстах, чтобы проверить и посмотреть, как работает ваш код, когда установлены различные переменные среды.

Например, если вы хотите, чтобы он возвращал значение BitLockerProvisioning при запуске Get-SMSTsVariable -VariableName _SMSTSCurrentActionName и возвращал 'C:' при запуске _OSDDetectedWinDir, вы устанавливаете макет следующим образом:

mock Get-SMSTsVariable `
   -parameterFilter { $VariableName -eq '_SMSTSCurrentActionName'} `
   -mockWith {return 'BitLockerProvisioning'}

mock Get-SMSTsVariable `
   -parameterFilter { $VariableName -eq '_OSDDetectedWinDir'} `
   -mockWith {return 'C:'}

Таким образом, вы можете начать тестирование, настроив несколько ответов для различных способов работы ваших функций. Это действительно бриз.

0 голосов
/ 30 апреля 2020

С Pester 4.3.3+ вы можете использовать New-MockObject для создания полезного макета этого COM-объекта.

В качестве альтернативы, вы можете сделать что-то похожее на ниже, чтобы позволить вам смоделировать функциональность COM-объекта.

Если этот COM-объект доступен на машинах, где работает ваш CI, я мог бы рассмотреть вопрос о пропуске макетов и написании интеграционного теста.

# functions.ps1

Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop";


function GetTaskSequenceValue(
    [Parameter(Mandatory=$true)]
    [string] $varNameToRead,    

    [Parameter(Mandatory=$false)]
    [System.Management.Automation.ScriptBlock] $readAction = {
        param([string] $readKey)
            $tsEnv = New-Object -COMObject 'Microsoft.SMS.TSEnvironment'
            $tsEnv.Value($readKey)
    }
) {
    $value = Invoke-Command `
        -ScriptBlock $readAction `
        -ArgumentList @($varNameToRead)

    return $value
}


function SetTaskSequenceValue(
    [Parameter(Mandatory=$true)]
    [string] $varNameToWrite,   

    [Parameter(Mandatory=$false)]
    [System.Management.Automation.ScriptBlock] $writeAction = {
        param([string] $writeKey, [string] $value)
            $tsEnv = New-Object -COMObject 'Microsoft.SMS.TSEnvironment'
            $TsEnv.Value($writeKey) = $value   
    }    
) {    
    try {
        Invoke-Command `
            -ScriptBlock $writeAction `
            -ArgumentList @($varNameToWrite)

        return $true
    }
    catch {
        # Swallow it
    }
    return $false
}

Тесты для функций абов. Тесты вручную макетируют объекты COM

# functions.test.ps1

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


Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop";


Describe "GetTaskSequenceValue" {
    It "gets the expected value" {
        $expected = 'value'
        $mockAction = { 
            param($dummy)  
                return 'value'
        }
        $actual = GetTaskSequenceValue `
            -varNameToRead 'dummyName' `
            -readAction $mockAction
        $actual | Should Be $expected
    }
}


Describe "SetTaskSequenceValue" {
    It "sets the expected value" {
        $expected = 'value'
        $mockAction = { 
            param($dummy)  
                return 'value'
        }
        $actual = SetTaskSequenceValue `
            -varNameToWrite 'dummyValue' `
            -writeAction $mockAction 
        $actual | Should Be $true
    }
}

...