【问题标题】:PowerShell Pester Mock Rest API CallsPowerShell Pester Mock Rest API 调用
【发布时间】:2021-07-26 15:42:18
【问题描述】:

是否有任何简单的方法可以模拟 Pester 中的 Rest API 调用

这是我的代码,我只需要在 Pester 中模拟那些 Rest API 调用 并对其进行测试,有人可以在这里帮助我吗?

Describe 'Test worldclockapi.com' {
    BeforeAll {
        $response = Invoke-WebRequest -Method 'GET' -Uri 'http://worldclockapi.com/api/json/utc/now'
        $responseContent = $response.Content | ConvertFrom-Json
        Write-Output $responseContent
    }

    It 'It should respond with 200' {
        $response.StatusCode | Should -Be 200
    }
    
    It 'It should have a null service response' {
        $responseContent.serviceResponse | Should -BeNullOrEmpty
    } 
    
    It 'It should be the right day of the week' {
        $dayOfWeek = (Get-Date).DayOfWeek
        $responseContent.dayOfTheWeek | Should -Be $dayOfWeek
    }
    
    It 'It should be the right year' {
        $year = Get-Date -Format 'yyyy'
        $responseContent.currentDateTime | Should -BeLike "*$year*"
    }
    
    It 'It should be the right month' {
        $month = Get-Date -Format 'MM'
        $responseContent.currentDateTime | Should -BeLike "*$month*"
    }
    
    # These two tests assume you are running this outside daylight savings (during the winter) .. hacky but good way to showcase the syntax ;)
    It 'It should not be daylight savings time' {
        $responseContent.isDayLightSavingsTime | Should -Not -Be $true
    }
    
    It 'It should not be daylight savings time another way' {
        $responseContent.isDayLightSavingsTime | Should -BeFalse
    }
}

【问题讨论】:

  • 你需要模拟 Get-RestMethod 命令

标签: powershell api pester pester-5


【解决方案1】:

使用真实响应作为模拟输出的模板可能是最简单的方法。

Invoke-WebRequest -Method 'GET' -Uri 'http://worldclockapi.com/api/json/utc/now' | 
    Export-Clixml .\response.xml

上述命令会将来自 API 的真实响应序列化到文件中。

现在我们可以导入文件以用于我们的模拟。只需使用Mock 命令来定义我们的模拟。

Mock

  • -CommandName :我们正在模拟的命令
  • -ParameterFilter:一个可选过滤器,用于将模拟行为限制为仅使用 CommandName ,其中传递给命令的参数值通过过滤器。此 ScriptBlock 必须返回一个布尔值。
  • -MockWith:一个 ScriptBlock 指定将用于模拟 CommandName 的行为。默认值为空的 ScriptBlock。我们在这里导入文件作为我们的输出。
Mock -CommandName Invoke-WebRequest -ParameterFilter { $Method -eq 'GET' } -MockWith { Import-Clixml .\response.xml }

现在,当使用 -Method 'Get' 调用 Invoke-WebRequest 时,我们的 mock 将被调用,并将返回我们使用 Import-CliXml(或其他方法 - json、xml 等)导入的对象。
注意: 模拟命令必须出现在对我们正在模拟的命令的任何调用之前。还要注意,即使在使用该命令的其他函数内部也会调用模拟。

    BeforeAll {
        Mock -CommandName Invoke-WebRequest -ParameterFilter { $Method -eq 'GET' } -MockWith { Import-Clixml .\response.xml }

        # on this next line our mock will be called instead and will return our prepared object
        $response = Invoke-WebRequest -Method 'GET' -Uri 'http://worldclockapi.com/api/json/utc/now'
        $responseContent = $response.Content | ConvertFrom-Json
        Write-Output $responseContent
    }

【讨论】:

    【解决方案2】:

    我认为Daniel's answer 很棒,但是如果您正在处理大型或共享存储库,那么您只需要小心管理这些 XML 文件。我使用的另一种选择是使用真实响应为所有返回的对象创建一个大型 Json 文件。它可以导入BeforeAllBeforeDiscovery,具体取决于您的测试结构。

    我补充答案的原因实际上也只是为了涵盖错误响应,因为拥有显示您如何处理 REST 调用失败的测试用例非常重要。在您自己的函数中包装 Invoke-WebRequest 可能有助于返回个性化错误、处理标头响应以及为站点名称或允许的 API 路径集提供常量。例如,根据 PowerShell 的版本,这就是我处理 404 的方式。

    Context " When a path does not exist in the API" {
        BeforeAll {
            Mock Invoke-WebRequest {
                # Use the actual types returned by your function or directly from Invoke-WebRequest.
                if ($PSVersionTable.PSEdition -eq "Desktop") {
                    $WR = New-MockObject -Type 'System.Net.HttpWebResponse'
                    $Code = [System.Net.HttpStatusCode]::NotFound
                    # Use Add-Member because StatusCode is a read-only field on HttpWebResponse
                    $WR | Add-Member -MemberType NoteProperty -Name StatusCode -Value $Code -Force
                    $Status = [System.Net.WebExceptionStatus]::ProtocolError
                    $Ex = [System.Net.WebException]::new("404", $null, $Status, $WR)
                }
                else {
                    $Message = [System.Net.Http.HttpResponseMessage]::new()
                    $Message.StatusCode = [System.Net.HttpStatusCode]::NotFound
                    $Ex = [Microsoft.PowerShell.Commands.HttpResponseException]::new("404", $Message)
                }
                throw $Ex
            } -ParameterFilter {
                $Uri -eq "http://worldclockapi.com/api/json/utc/NEVER" -and
                $Method -eq "Get"
            }
    
            $GetRestTimeParams = @{
                Uri   = "http://worldclockapi.com/api/json/utc/NEVER"
                Method = "Get"
            }
        }
    
        It " Get-RestTime should not run successfully" {
            { Get-RestTime @GetRestTimeParams } | Should -Throw
        }
    
        It " Get-RestTime should throw a 404 error" {
            $ShouldParams = @{
                # Use the actual types returned by your function or directly from Invoke-WebRequest.
                ExceptionType   = [System.Net.WebException]
                ExpectedMessage = "404: NotFound"
            }
            {
                Get-RestTime @GetRestTimeParams
            } | Should -Throw @ShouldParams
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2021-04-26
      • 1970-01-01
      • 2023-02-07
      • 1970-01-01
      • 1970-01-01
      • 2016-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多