繁体   English   中英

Pester:并非所有模拟函数都被拦截

[英]Pester: not all mocked functions are intercepted

我有许多模块,包括ModuleMainModuleSql 模块之间存在相互依赖关系,因此 ModuleMain 中的Main-Function使用 ModuleSql 中的 4 个函数:

function Main-Function {
  [CmdletBinding(SupportsShouldProcess=$true)]

  # The following 4 lines are all wrapped in $PSCmdlet.ShouldProcess() and
  # try {} catch {} logic. I have left that out in this post, but I mention
  # it in case it is relevant.

  $a = New-SqlConnection
  $b = Invoke-SqlStoredProc -connection $a
  $c = Invoke-SqlQuery -connection $a
  Close-SqlConnection -connection $a | Out-Null
  return $c
}

我创建了一个Function-Main1.tests.ps1文件来测试 Function-Main1。 起初我使用InModuleScope但后来切换到使用-ModuleName参数指定每个模拟的模块。

Import-Module "ModuleMain" -Force

Describe "Main-Function" {

  Mock -ModuleName ModuleMain New-SqlConnection {
    return $true }
  Mock -ModuleName ModuleMain Invoke-SqlStoredProc {
    return $true }
  Mock -ModuleName ModuleMain Invoke-SqlQuery {
    return $true }
  Mock -ModuleName ModuleMain Close-SqlConnection {
    return $true }

  Context "When calling Main-Function with mocked SQL functions" {
    It "Calls each SQL function once" {
      Assert-MockCalled -Scope Context -ModuleName ModuleMain -CommandName New-SqlConnecion -Times 1 -Exactly
      Assert-MockCalled -Scope Context -ModuleName ModuleMain -CommandName Invoke-SqlStoredProc -Times 1 -Exactly
      Assert-MockCalled -Scope Context -ModuleName ModuleMain -CommandName Invoke-SqlQuery -Times 1 -Exactly
      Assert-MockCalled -Scope Context -ModuleName ModuleMain -CommandName Close-SqlConnecion -Times 1 -Exactly
    }
  }
}

当我运行这个测试时,我得到以下结果:

[-] Calls each SQL function once 223ms
  Expected Invoke-SqlStoredProc in module ModuleMain to be called 1 times exactly but was called 0 times
  at line: xx in 
  xx:       Assert-MockCalled -Scope Context -ModuleName ModuleMain -CommandName Invoke-SqlStoredProc -Times 1 -Exactly

请注意以下事项:

  1. 我没有导入定义了-Sql函数的ModuleSql ,因为无论如何我都在嘲笑它们。
  2. 我已经观察/计算出我需要将-ModuleName设置为定义Main-Function的模块,而不是定义 SQL 函数(我试图模拟的)的模块。
  3. 我玩过InModuleScope-ModuleName ,例如将一个或另一个设置为ModuleSQL ,但主要是这让事情变得更糟。

通过在其他模拟函数中添加 Verbose 输出,我确认New-SqlConnectionClose-SqlConnection都被拦截,但Invoke-SqlStoredProcInvoke-SqlQuery没有被拦截。

深入探究,我可以看到Invoke-Sql*Invoke-Sql* )函数抛出以下异常:错误:“从 'System.Boolean' 到 'System.Data.SqlClient.SqlConnection' 的无效转换。” 我在调用这些函数的真实版本时所期望的行为,但我期望模拟版本会忽略参数类型。

为什么 Pester 只会拦截我的 4 个函数中的 2 个?

因此,在上面的评论中给出了对这个问题的简短回答:

模拟函数不会忽略参数类型。 --宠物系列

这意味着当我尝试调用Invoke-Sql*函数并使用虚假的$sqlConnection变量(简单地设置为$true )时,这会导致错误,因为输入参数不是预期的数据类型。

在我的情况下,解决方案是模拟New-SqlConnection函数,因此它返回一个[System.Data.SqlCient.SqlConnection]对象。 碰巧的是,我也恢复使用InModuleScope而不是在每个 Mock 上指定模块:

InModuleScope "ModuleMain" {
  Describe "MainFunction" {

    Mock New-SqlConnection {
      New-Object -TypeName System.Data.SqlCient.SqlConnection
    }

    ...
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM