I have a PowerShell script for setting up a website in IIS. It includes the following function:
function Set-IisWebsiteBinding (
[Parameter(Mandatory = $true)]
[string]$SiteName,
[Parameter(Mandatory = $true)]
[Microsoft.Web.Administration.Site]$Website,
[Parameter(Mandatory = $true)]
[array]$WebsiteBindingSettings
)
{
# Set up website bindings ...
}
I'm trying to write tests for the function in Pester. I'd like to create a dummy $Website object to pass to the function under test. The problem is that the Microsoft.Web.Administration.Site
type has no constructor. How can I create an object of type Microsoft.Web.Administration.Site
in PowerShell if it has no constructor?
I could create one via IISServerManager.Sites.CreateElement()
but I'd like to avoid having to depend on using a real IISServerManager
. Alternatively, I could get rid of the type coercion for the function parameter $Website
, to allow the test code to pass in a hashtable instead of a Microsoft.Web.Administration.Site object. However, I'd prefer to keep the type coercion so it's obvious to future maintainers of the script what the type of the $Website
object is.
Is there any way around this lack of a constructor without using a real IISServerManager
or removing the type coercion?
Pester provides an easy option to create an object for a type that doesn't offer a public constructor via New-MockObject
:
$instance = New-MockObject -Type ([Microsoft.Web.Administration.Site])
Alternatively you can use the same API used by Pester to create it, FormatterServices.GetUninitializedObject(Type)
.
In both cases as noted in comments and still worth adding is that you will need to have the IISAdministration Module or its assembly loaded.
Add-Type '
public class MyType
{
private MyType() { }
}'
$instance = [System.Runtime.Serialization.FormatterServices]::GetUninitializedObject([MyType])
$instance.GetType()
# Namespace:
#
# Access Modifiers Name
# ------ --------- ----
# public class MyType : object
If you're curious, the method essentially uses an internal API in RuntimeType
: RuntimeHelpers.CoreCLR.cs#L330-L345
. Not sure what it uses for .NET Framework, code is closed source.
$methodInfo = [MyType].GetType().GetMethod(
'GetUninitializedObject',
[System.Reflection.BindingFlags] 'NonPublic, Instance')
$methodInfo.Invoke([MyType], @())