Трудно издеваться над BasicHtmlWebResponseObject Invoke-WebRequest - PullRequest
2 голосов
/ 12 февраля 2020

Я пытаюсь протестировать этот раздел функции PowerShell:

# post
$Response = Invoke-WebRequest -Method POST -Uri $Uri -Body $Body -ContentType 'application/xml'

# parse Response.Content; return as System.Xml.XmlDocument
[xml]$Response.Content

, высмеивая BasicHtmlWebResponseObject, который возвращается Invoke-WebRequest:

Mock Invoke-WebRequest { 

    $WebResponse = [System.Net.HttpWebResponse]::new()
    [System.Net.HttpWebResponse].GetField('m_StatusCode', 'NonPublic, Instance').SetValue(
        $WebResponse,
        200,
        'NonPublic,SetField',
        $null,
        (Get-Culture)
    )

    $Content = '<?xml version="1.0" encoding="UTF-8"?><response><control>failure<status></status></control><operation><result><status>failure</status></result></operation></response>'
    $Response = [Microsoft.PowerShell.Commands.BasicHtmlWebResponseObject]::new($WebResponse,$Content)
    return $Response
}

Это утверждение не удается, потому что я не создаю HttpWebResponse или BasicHtmlWebResponseObject правильно:

It "returns the response's Content object" {
    # act
    $Content = Send-Request -Session $Session

    # assert
    Assert-MockCalled Invoke-WebRequest
    $Content | Should -BeOfType [xml]
    $Content.response.control.status | Should -Be 'success'
    $Content.response.operation.result.status | Should -Be 'success'
}

** edit **

Я думал об использовании New-MockObject:

Mock Invoke-WebRequest { 
    $Response = New‐MockObject -Type Microsoft.PowerShell.Commands.BasicHtmlWebResponseObject
    $Response.Content = '<?xml version="1.0" encoding="...'
}

но свойство Content доступно только для чтения.

** / edit **

Чего мне не хватает?

Ответы [ 3 ]

1 голос
/ 12 февраля 2020

Это работает:

Mock Invoke-WebRequest { 
    $Response = New-MockObject -Type  Microsoft.PowerShell.Commands.BasicHtmlWebResponseObject
    $Content = `
        '<?xml version="1.0" encoding="UTF-8"?>
        <response>
            <control><status>success</status></control>
            <operation><result><status>success</status></result></operation>
        </response>'
    $Response | Add-Member -NotePropertyName Content -NotePropertyValue $Content -Force
    $Response
}
1 голос
/ 13 февраля 2020

Немного более простой альтернативой может быть обернуть ваш invoke-webrequest в функцию и просто смоделировать это вместо этого. Например,

function Get-XmlFromUri
{
    param( $Uri, $Method, $Body )
     $Response = Invoke-WebRequest -Method $Method -Uri $Uri -Body $Body -ContentType 'application/xml’
    [xml]$Response.Content
}

Теперь вы можете смоделировать Get-XmlFromUri и просто вернуть объект System. Xml .XmlDocument из жестко запрограммированного xml, который гораздо проще создать, чем BasicHtmlWebResponseObject, который требует вызовов отражения

Mock Get-XmlFromUri { 
    [xml] '<?xml version="1.0" encoding="UTF-8"?>
    <response>
        <control><status>success</status></control>
        <operation><result><status>success</status></result></operation>
    </response>'
}

Или, в зависимости от того, насколько ваш код должен соответствовать BasicHtmlWebResponseObject, вы можете просто вернуть хеш-таблицу из вашего макета invoke-webrequest, который имеет нужные вам свойства:

Mock Invoke-WebRequest { 
    new-object pscustomobject -property @{
        Content = '<?xml version="1.0" encoding="UTF-8"?>
    <response>
        <control><status>success</status></control>
        <operation><result><status>success</status></result></operation>
    </response>’
    }
}

(извиняюсь за форматирование кода - в настоящее время печатать одной рукой iPhone в 4 часа утра с не очень сонным ребенком: -S)

1 голос
/ 12 февраля 2020

В PowerShell Core это не работает для меня:

[System.Net.HttpWebResponse].GetField('m_StatusCode', 'NonPublic, Instance')

И именно поэтому ваш Mock не возвращает то, что вы ожидаете. Однако эта строка работает на Windows PowerShell. Не уверен, что правильный эквивалент на PSCore, нуждается в исследовании, но думал, что я покажу вам это далеко.

...