Unit testing a Powershell Azure Function App?

huangapple go评论66阅读模式
英文:

Unit testing a Powershell Azure Function App?

问题

I have an Azure Function written in Powershell:

function Invoke {
    param($Request)
    Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
        StatusCode = [HttpStatusCode]::OK
        Body       = "Hello!"
    })
}

I have a Pester unit test for this function:

Describe "Invoke" {
    It "Returns a 200 response" {
        $Response = Invoke -Request [HttpRequestContext]@{}
        $Response.StatusCode | Should Be ([HttpStatusCode]::OK)
    }
}

Running this test yields:

Describing Invoke
  [-] Returns a 200 response 4ms (3ms|1ms)
   RuntimeException: Unable to find type [HttpRequestContext].

Presumably the PowerShellWorker injects these types when it runs the script and so they are not available when Pester invokes the test. In falling order of desirability, how can I:

  1. Import these types in my test run? For example, is there a module I could import?
  2. Inject mocks of these types? Pester has support for creating mocks of objects, but not inject types?
  3. Ask the PowerShellWorker to invoke the function from my test? (I could probably invoke func host start and write integration tests instead, but I would really prefer to have unit tests if possible.)

I'd appreciate any lead that can help me with this.

UPDATE: As pointed out in comments, I had deleted a param() when compacting my example. To clarify, the idea is to support type annotations in both test and production code.

UPDATE2: Corrected spelling as per mclayton's suggestion.

英文:

I have an Azure Function written in Powershell:

function Invoke {
    param($Request)
    Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
        StatusCode = [HttpStatusCode]::OK
        Body       = "Hello!"
    })
}

I have a Pester unit test for this function:

Describe "Invoke" {
    It "Returns a 200 response" {
        $Response = Invoke -Request [HttpRequestContext]@{}
        $Response.StatusCode | Should Be ([HttpStatusCode]::OK)
    }
}

Running this test yields:

Describing Invoke
  [-] Returns a 200 response 4ms (3ms|1ms)
   RuntimeException: Unable to find type [HttpRequestContext].

Presumably the PowerShellWorker injects these types when it runs the script and so they are not available when Pester invokes the test. In falling order of desirability, how can I:

  1. Import these types in my test run? For example, is there a module I could import?
  2. Inject mocks of these types? Pester has support for creating mocks of objects, but not inject types?
  3. Ask the PowerShellWorker to invoke the function from my test? (I could probably invoke func host start and write integration tests instead, but I would really prefer to have unit tests if possible.)

I'd appreciate any lead that can help me with this.

UPDATE: As pointed out in comments, I had deleted a param() when compacting my example. To clarify, the idea is to support type annotations in both test and production code.

UPDATE2: Corrected spelling as per mclayton's suggestion.

答案1

得分: 1

我尚未看到一种真正简洁的方法来进行 PowerShell Azure Functions 的单元测试...或者至少它们确实没有像 C#/Javascript/Python 一样受到普遍的关注。

然而,你可以在 Pester 中使用 New-MockObject 来模拟类型。

我还看到一些使用 entryPoints 来运行脚本,然后独立测试脚本而不必依赖于 Azure Function 的工作时环境的方法,但你想要深入探讨多深入呢?

英文:

I've not seen a really concise approach to unit testing PowerShell Azure Functions....or at least they certainly get less love than C#/Javascript/Python in general.

You can however mock the type in pester using New-MockObject

I've also seen ways of using entryPoints to run a script and then test the script independently of your Azure Function so you don't have to rely on the worker runtime at all but how deep down the rabbit hole do you want to go?!

答案2

得分: 0

我今天遇到了这个问题,通过将run.ps1中的using语句移到profile.ps1文件的顶部,并在BeforeEach中的单元测试中添加一个模拟类型,然后再点源run.ps1来解决它:

enum HttpStatusCode {
    OK
    InternalServerError
}
class HttpResponseContext {
    [HttpStatusCode]$StatusCode
    [string]$ContentType
    [string]$Body
}
function Push-OutputBinding($Name, $Value) {}

对我来说起到了奇效。

英文:

I just ran into this today, and I solved it by moving the using statement in run.ps1 to the top of the profile.ps1 file, and adding a mock type to the unit tests in the BeforeEach, before dot-sourcing run.ps1:

enum HttpStatusCode {
    OK
    InternalServerError
}
class HttpResponseContext {
    [HttpStatusCode]$StatusCode
    [string]$ContentType
    [string]$Body
}
function Push-OutputBinding($Name, $Value) {}

Worked like a charm for me.

huangapple
  • 本文由 发表于 2023年5月26日 15:53:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/76338754.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定