Reputation: 4659
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:
-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.InModuleScope
and -ModuleName
, e.g. 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?
Upvotes: 3
Views: 2019
Reputation: 4659
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
}
...
}
Upvotes: 4