Pester
Pester copied to clipboard
Cant use New-MockObject with custom class from within a module
Checklist
- [X] Issue has a meaningful title
- [X] I have searched the existing issues. See all issues
- [X] I have tested using the latest version of Pester. See Installation and update guide.
What is the issue?
Synopsis: When trying to calling New-MockObject -Type 'Config' where Config is a class defined in another psm1 file, I get the following error PSInvalidCastException: Cannot convert the "Config" value of type "System.String" to type "System.Type"
Using Powershell 5.1 with Pester V5.6.1
I have put together the following simple sample to demonstrate the problem
- Client depends on Config
- Client.Tests depends on Config & Client
- Not sure if this is important, but Client has a using statement for Config, and therefore transitively, Client.Tests has 2 using calls to Config, 1 in Client.Tests and another in Client
All files are in the same directory
Config.psm1
class Config
{
[ValidateLength(1, 1000)]
[string] $A
[ValidateLength(1, 1000)]
[string] $B
Config( [string] $pathToJson)
{
try
{
$jsonContent = Get-Content -Path $pathToJson -Raw | ConvertFrom-Json
$this.A = $jsonContent.A
$this.B = $jsonContent.B
}
catch
{
Write-Warning $_.Exception.Message
Write-Warning "Check json file for missing value(s)"
throw "Error loading configuration from file: $($_.Exception.Message)"
}
}
}
Export-ModuleMember -Function Config
Client.psm1
using module .\Config.psm1
class Client
{
[Config] $config
Client([Config] $config)
{
$this.config = $config
}
[string] JoinAandB()
{
return $this.config.A + $this.config.B
}
}
Export-ModuleMember -Function Client
Client.Tests.psm1
using module .\Config.psm1
using module .\Client.psm1
Describe "SomeClassThatUsesAzureDevOpsAgentConfig" {
It "JoinAandB__A_and_B_Are_Populated__ReturnsAB" {
# Arrange
$mockConfig = New-MockObject -Type 'Config' -Properties {A = "foo" B = "Bar"}
$systemUnderTest = New-Object Client($mockConfig)
$expectedResult = "AB"
# Act
$actualResults = $objectUnderTest.JoinAandB()
# Assert
$actualResults | Should -Be $expectedResult
}
}
I'm not including the JSON since its not relevant, as I am trying to mock the config class, so it should not be needed.
The Error message I get when I run Invoke-Pester .\Client.Tests.ps1
Starting discovery in 1 files.
Discovery found 1 tests in 16ms.
Running tests.
[-] SomeClassThatUsesAzureDevOpsAgentConfig.JoinAandB__A_and_B_Are_Populated__ReturnsAB 5ms (5ms|1ms)
PSInvalidCastException: Cannot convert the "Config" value of type "System.String" to type "System.Type".
ArgumentTransformationMetadataException: Cannot convert the "Config" value of type "System.String" to type "System.Type".
ParameterBindingArgumentTransformationException: Cannot process argument transformation on parameter 'Type'. Cannot convert the "Config" value of type "System.String" to type "System.Type".
at <ScriptBlock>, C:\Users\dgleason\source\repos\DevOpsTeam\IaC\installs\azure_devops_agent_configuration\Client.Tests.ps1:9
Tests completed in 77ms
Tests Passed: 0, Failed: 1, Skipped: 0, Inconclusive: 0, NotRun: 0
The weird thing is, when I was developing my unit tests, they were all passing, it wasn't until some point till I made it to my 6th or 7th test that it started failing. This makes me think the way I had my module loaded in my IDE (VS Code) bypassed the issue.
Expected Behavior
Calling New-MockObject -Type 'Config' should return my mocked class
Steps To Reproduce
Executing Invoke-Pester .\Client.Tests.ps1 from current working directory in IDE terminal after closing and reopenning, or via new Powershell window to avoid any caching of classes/modules.
Describe your environment
Pester version : 5.6.1 C:\Program Files\WindowsPowerShell\Modules\Pester\5.6.1\Pester.psm1 PowerShell version : 5.1.19041.4648 OS version : Microsoft Windows NT 10.0.19045.0
Possible Solution?
No response
Closing the loop on this, I was able to make this work by changing -Type 'Config' to -Type ([Config]) - credit for the answer goes to @mklement0 at https://stackoverflow.com/questions/78979730/how-to-use-pester-new-mockobject-with-class-from-within-a-module
However, I'm not sure why this works, I think the documentation at the very least should be updated.
Glad you figured it out. Likely same explanation as this.
Let's leave this open to update matching docs as you've suggested. 🙂
If you or someone would like to contribute a PR, I suggest adding a note about using parantheses around type-values in -Type parameter help + a fixed example in https://github.com/pester/Pester/blob/main/src/functions/New-MockObject.ps1.