Pester
Pester copied to clipboard
Should -BeOfType should support custom types
1. General summary of the issue
PowerShell supports custom object types via the PSTypeNames parameter on PSObject instances. Pester has a -BeOfType parameter on the Should command to allow testers to verify if an object is of a given type. At the time of this writing, Should -BeOfType only supports checking against actual .NET types. It would be very helpful if Pester also supported custom type names here, such that the internal logic first looked at the actual type, and if the actual type was of type PSObject and PSObject was not a match for the type being looked for, then looked at the PSTypeNames collection to see if the required type name was contained within that collection.
@KirkMunro Thanks for the suggestion, does -is work with custom types? I guess not? If not then I am not sure if overloading the meaning of this operator is the best idea. It would sure be convenient, and maybe opting-out, to be able to check just types or just PSTypeName would be, the best way to go here. What do you think? :)
You can see a test where I am checking for type PSObject and then looking at the PSTypeNames collection here. That approach aside, I think custom objects are very common in PowerShell (in the case of the test I linked to i was an actual type, but was deserialized), to the point where it would be useful to have a simple test.
The -is operator does not currently work with custom types; however, PowerShell allows you to define a parameter type as [PSTypeName('CustomTypeNameHere')], and it will verify that the object passed into the parameter is custom and of the appropriate custom type. I believe it would be useful if the -is operator allowed for the same validation check, and have considered submitting that request against PowerShell. If that were to happen, would Pester automatically support custom type checking using the same syntax (e.g. `Should -BeOfType [PSTypeName('CustomTypeNameHere')])?
I also considered submitting this issue as a request for a -BeOfCustomType parameter. Thoughts on that?
If that were to happen, would Pester automatically support custom type checking using the same syntax (e.g. `Should -BeOfType [PSTypeName('CustomTypeNameHere')])?
Yes that should work, the assertion is using -is to do the checking.
I also considered submitting this issue as a request for a -BeOfCustomType parameter. Thoughts on that?
Might be worth checking what the PS team thinks about integrating the behavior into -is. If they reject because they want to keep differentiating the actual and ps types then having two assertions would be better and would lead to less confustion. Otherwise having just one is better (and would work automatically).
I think that -HavePSTypeName would be the most accurate description, but -HavePSType, -BeOfPSType would fit both the name and the alias better.
It would be great to see a clean solution for this. I'm currently using Pester 5.1.1 and the following workaround:
(Get-CustomThing).GetType().Name | Should -Be "MyCustomeType"
Either PowerShell/PowerShell#10750 is resolved or, as a workaround, if the first -is match fails, try the GetType().Name method. Definitely also log that it was matching for a custom type.
If implemented this way it would still work in downstream testing (e.g. 5.1+)
@nohwnd this is something I think I could figure out a PR for if you're interested.
The PowerShell PR is stuck and won't reach all users of Pester, so I think we should support this.
I would suggest a switch like -UsePSTypeNames to be explicit when we check it.
Automatic fallback will make it harder to deprecate later if moved to it's own function or parameter set later - or replaced by native support.
I think I changed my mind. Making it consider both real type, and PSType by default does not seem to be such a bad thing. When user sets the type, they are unlikely to set it to something random or stupid (like System.Object), but rather purposefully set it to either:
- Distinguish their own "type" from other PSObjects -> e.g. Person
- Make their own "type" similar to an actual type -> e.g. System.Diagnostics.Process
The room for error is there, but I'd rather learn how to do it right when it bites me maybe once, than always have to remember specifying UsePSTypeNames.
Second best option is imho having a separate parameter for it:
I think that -HavePSTypeName would be the most accurate description, but -HavePSType, -BeOfPSType would fit both the name and the alias better.