1
votes

Comment se moquer d'une commande appelée deux fois avec des paramètres différents et des résultats différents

J'ai une fonction PowerShell que je veux tester avec Pester:

function ExecuteInstallRequiredModule ()
{
    Install-RequiredModule -ModuleName 'TestModule' -RepositoryName 'TestRepo' `
        -ProxyUrl 'http://myproxy'
}

Describe 'Install-RequiredModule' {

    $securePassword = "mypassword" | 
        ConvertTo-SecureString -asPlainText -Force
    $psCredential = New-Object System.Management.Automation.PSCredential  ('MyUserName', $securePassword)
    Mock Get-Credential { return $psCredential }

    # Want to add an error to $Error without it being written to the host.
    Mock Install-Module { Write-Error "Some error" -ErrorAction SilentlyContinue } `
        -ParameterFilter { $Name -eq  'TestModule' -and $Repository -eq 'TestRepo' -and $ErrorAction -eq 'SilentlyContinue' -and $WarningAction -eq 'SilentlyContinue'}
    Mock Install-Module { return $Null } `
        -ParameterFilter { $Name -eq  'TestModule' -and $Repository -eq 'TestRepo' -and $Proxy -eq 'http://myproxy' -and $ProxyCredential -eq $psCredential }

    Mock Get-InstalledModule { return @('Non-null text') }

    It 'attempts to install module a second time if first attempt fails' {
        ExecuteInstallRequiredModule
        #Assert-VerifiableMock
        #Assert-MockCalled Install-Module -Scope It -Times 2
    }
}

Cette fonction peut appeler Install-Module deux fois. Il essaie d'abord sans informations d'identification proxy, comme s'il avait un accès direct à Internet. Si cela échoue, il tente à nouveau, cette fois avec les informations d'identification du proxy.

Comment puis-je tester cette fonctionnalité avec Pester?

J'ai lu dans les forums PowerShell, ici , que je devrais être capable de me moquer de la même commande deux fois avec des filtres de paramètres différents. Voici donc ce que j'ai essayé:

function Install-RequiredModule (
    [string]$ModuleName,
    [string]$RepositoryName,
    [string]$ProxyUrl
    )
{
    # Errors from Install-Module are non-terminating.  They won't be caught using  
    # try - catch.  So check $Error instead.
    # Clear errors so we know if one shows up it must have been due to Install-Module.
    $Error.Clear()

    # Want to fail silently, without displaying anything in console to scare the user, 
    # because it's valid for Install-Module to fail for a user behind a proxy server.
    Install-Module -Name $ModuleName -Repository $RepositoryName `
        -ErrorAction SilentlyContinue -WarningAction SilentlyContinue

    if ($Error.Count -eq 0)
    {
        # throw 'NO error'
        return
    }

    # There was an error so try again, this time with proxy details.

    $proxyCredential = Get-Credential -Message 'Please enter credentials for proxy server'

    # No need to Silently Continue this time.  We want to see the error details.
    $Error.Clear()

    Install-Module -Name $ModuleName -Repository $RepositoryName `
        -Proxy $ProxyUrl -ProxyCredential $proxyCredential

    if ($Error.Count -gt 0)
    {
        throw $Error[0]
    }

    if (-not (Get-InstalledModule -Name $ModuleName -ErrorAction SilentlyContinue))
    {
        throw "Unknown error installing module '$ModuleName' from repository '$RepositoryName'."
    }

    Write-Output "Module '$ModuleName' successfully installed from repository '$RepositoryName'."
}

Décommentant la ligne dans la fonction sous test qui dit # throw 'NO error' Je trouve que le $ Error.Count est 0 après le premier appel à Install-Module. Ainsi, le simulacre qui crée une erreur sans fin n'est pas appelé et la fonction retourne avant le deuxième appel à Install-Module.


0 commentaires

3 Réponses :


1
votes

Vous pouvez appeler la commande install-module avec -ErrorAction Stop dans une boucle try catch.

try
{
    #run with no credentials
    Install-Module -Name $ModuleName -Repository $RepositoryName -ErrorAction stop -WarningAction SilentlyContinue
}
catch
{
    #when fails, run with proxy credentials
    Install-Module -Name $ModuleName -Repository $RepositoryName -Proxy $ProxyUrl -ProxyCredential $proxyCredential
}

Vous pouvez avoir plusieurs Bloc catch {} pour la même commande try qui intercepterait différents types d'échecs et exécuterait un bloc de script de votre choix.


0 commentaires

2
votes

Le problème semble être que Pester bloque le filtrage sur des paramètres communs, donc votre utilisation de "ErrorAction", etc. entraîne l'échec de votre filtre.

Vous pouvez voir les paramètres supprimés des fonctions simulées vers la ligne 254 dans le code de simulation de Pester: Mock.ps1

Et aussi, tester cette suppression est l'un des propres tests unitaires de Pester (ligne 283): Mock.tests.ps1


0 commentaires

0
votes

Pour toute personne se trouvant dans une situation similaire, voici la version finale du test qui a fonctionné:

function Install-RequiredModule (
    [string]$ModuleName,
    [string]$RepositoryName,
    [string]$ProxyUrl
    )
{
    try
    {
        Install-Module -Name $ModuleName -Repository $RepositoryName `
            -ErrorAction Stop

        return
    }
    catch {}

    # There was an error so try again, this time with proxy details.

    $proxyCredential = Get-Credential -Message 'Please enter credentials for proxy server'

    # No need to Silently Continue this time.  We want to see the error details.
    $Error.Clear()

    Install-Module -Name $ModuleName -Repository $RepositoryName `
        -Proxy $ProxyUrl -ProxyCredential $proxyCredential

    if ($Error.Count -gt 0)
    {
        throw $Error[0]
    }

    if (-not (Get-InstalledModule -Name $ModuleName -ErrorAction SilentlyContinue))
    {
        throw "Unknown error installing module '$ModuleName' from repository '$RepositoryName'."
    }

    Write-Output "Module '$ModuleName' successfully installed from repository '$RepositoryName'."
}

#region Tests *************************************************************************************

function ExecuteInstallRequiredModule ()
{
    Install-RequiredModule -ModuleName 'TestModule' -RepositoryName 'TestRepo' `
        -ProxyUrl 'http://myproxy'
}

Describe 'Install-RequiredModule' {

    $securePassword = "mypassword" | 
        ConvertTo-SecureString -asPlainText -Force
    $psCredential = New-Object System.Management.Automation.PSCredential  ('MyUserName', $securePassword)
    Mock Get-Credential { return $psCredential }

    Mock Install-Module { Write-Error "Some error" }
    Mock Install-Module { return $Null } -ParameterFilter { $Proxy -ne $Null -and $ProxyCredential -ne $Null }

    Mock Get-InstalledModule { return @('Non-null text') }

    It 'attempts to install module a second time, with proxy, if first attempt fails' {
        ExecuteInstallRequiredModule  
        Assert-MockCalled Install-Module -Scope It -Times 2 -Exactly
    }
}

#endregion


0 commentaires