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
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)"
}
}
}
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
}
}
Client.Tests.ps1
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 = [Client]::new($mockConfig)
$expectedResult = "fooBar"
# Act
$actualResults = $systemUnderTest.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
I have gone ahead and opened an issue in Pester Github page as well - https://github.com/pester/Pester/issues/2564
The following fixes your problem, but I'm not sure why:
-Type
, as a string ('Config'
), pass a [Type]
instance representing it; note the need to enclose the type literal ([...]
) in (...)
in order to pass it as such as a command argument:$mockConfig = New-MockObject -Type ([Config]) -Properties @{A = "foo"; B = "Bar"}
Similarly, [Client]::new($mockConfig)
only works because you're using the intrinsic new
method to call the constructor of the Client
class; the - normally equivalent - New-Object Client $mockConfig
statement would not (that said, using ::new()
is generally preferable).
Your symptoms are connected to code executing inside the It
statement, specifically.