简体   繁体   中英

Pester: not all mocked functions are intercepted

I have a number of modules, including ModuleMain and ModuleSql . There is an interdependence between the modules such that Main-Function in ModuleMain uses 4 functions from ModuleSql:

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
}

I have created a Function-Main1.tests.ps1 file to test Function-Main1. At first I used InModuleScope but then switched to specifying the module per-mock with the -ModuleName parameter.

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
    }
  }
}

When I run this test I get the following results:

[-] 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

Note the following:

  1. I did not import ModuleSql, where the -Sql functions are defined, since I am mocking them all anyway.
  2. I have observerd/worked out that I need to set -ModuleName to be the module where Main-Function is defined and not the one where the SQL function (that I am trying to mock) is defined.
  3. I have played around with InModuleScope and -ModuleName , eg setting one or other to be ModuleSQL , but mainly that just made things worse.

By playing around, adding Verbose output in the other mocked functions, I have confirmed that New-SqlConnection and Close-SqlConnection are both being intercepted, but Invoke-SqlStoredProc and Invoke-SqlQuery are not.

Probing deeper, I can see that the following exception is being thrown by the Invoke-Sql* (mocked) functions: Error: "Invalid cast from 'System.Boolean' to 'System.Data.SqlClient.SqlConnection'." This is behaviour that I would expect when the real versions of those functions are called, but I am expecting that the mocked versions would ignore parameter types.

Why would Pester intercept only 2 of my 4 functions?

So, the short answer to this question was given in the comments above:

Mocked functions does not ignore parameter types. --PetSerAl

This meant that when I was trying to call the Invoke-Sql* functions, and using the phony $sqlConnection variable (simply set to $true ) this was causing an error since the input parameter wasn't the expected data type.

And the solution in my case was to mock the New-SqlConnection function so it returned a [System.Data.SqlCient.SqlConnection] object. As it happens, I also reverted back to using InModuleScope rather than specifying the module on each Mock:

InModuleScope "ModuleMain" {
  Describe "MainFunction" {

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

    ...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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