Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem using Assert-MockCalled when dynamic parameter is using type from module #20

Open
johlju opened this issue Apr 20, 2019 · 1 comment

Comments

@johlju
Copy link
Contributor

johlju commented Apr 20, 2019

The stub cmdlet Move-ADDirectoryServer passes a string in the parameter Site. But the parameter Site is of the type Microsoft.ActiveDirectory.Management.ADReplicationSite which is a stub type.
When using an assert like below, the ToString() method does not return anything, neither does $Site.Name which is a property of the type Microsoft.ActiveDirectory.Management.ADReplicationSite.

Example of assert that fails.

Assert-MockCalled -CommandName Move-ADDirectoryServer -Times 1 -ParameterFilter {
    $Site.ToString() -eq $correctSiteName
}

The stub cmdlet looks like this.

function Move-ADDirectoryServer {
    <#
    .SYNOPSIS
        Move-ADDirectoryServer [-Identity] <ADDirectoryServer> [-Site] <ADReplicationSite> [-WhatIf] [-Confirm] [-AuthType <ADAuthType>] [-Credential <pscredential>] [-Server <string>] [<CommonParameters>]
    #>

    [CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact='Medium', HelpUri='http://go.microsoft.com/fwlink/?LinkId=219321')]
    param ( )

    dynamicparam {
        $parameters = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary

        # AuthType
        $attributes = New-Object System.Collections.Generic.List[Attribute]

        $attribute = New-Object System.Management.Automation.ParameterAttribute
        $attributes.Add($attribute)

        $parameter = New-Object System.Management.Automation.RuntimeDefinedParameter("AuthType", [Microsoft.ActiveDirectory.Management.ADAuthType], $attributes)
        $parameters.Add("AuthType", $parameter)

        # Credential
        $attributes = New-Object System.Collections.Generic.List[Attribute]

        $attribute = New-Object System.Management.Automation.ParameterAttribute
        $attributes.Add($attribute)

        $attribute = New-Object System.Management.Automation.ValidateNotNullOrEmptyAttribute
        $attributes.Add($attribute)

        $attribute = New-Object System.Management.Automation.CredentialAttribute
        $attributes.Add($attribute)

        $parameter = New-Object System.Management.Automation.RuntimeDefinedParameter("Credential", [System.Management.Automation.PSCredential], $attributes)
        $parameters.Add("Credential", $parameter)

        # Identity
        $attributes = New-Object System.Collections.Generic.List[Attribute]

        $attribute = New-Object System.Management.Automation.ValidateNotNullAttribute
        $attributes.Add($attribute)

        $attribute = New-Object System.Management.Automation.ParameterAttribute
        $attribute.Position = 0
        $attribute.Mandatory = $True
        $attribute.ValueFromPipeline = $True
        $attributes.Add($attribute)

        $parameter = New-Object System.Management.Automation.RuntimeDefinedParameter("Identity", [Microsoft.ActiveDirectory.Management.ADDirectoryServer], $attributes)
        $parameters.Add("Identity", $parameter)

        # Server
        $attributes = New-Object System.Collections.Generic.List[Attribute]

        $attribute = New-Object System.Management.Automation.ValidateNotNullOrEmptyAttribute
        $attributes.Add($attribute)

        $attribute = New-Object System.Management.Automation.ParameterAttribute
        $attributes.Add($attribute)

        $parameter = New-Object System.Management.Automation.RuntimeDefinedParameter("Server", [System.String], $attributes)
        $parameters.Add("Server", $parameter)

        # Site
        $attributes = New-Object System.Collections.Generic.List[Attribute]

        $attribute = New-Object System.Management.Automation.ParameterAttribute
        $attribute.Position = 1
        $attribute.Mandatory = $True
        $attributes.Add($attribute)

        $attribute = New-Object System.Management.Automation.ValidateNotNullAttribute
        $attributes.Add($attribute)

        $parameter = New-Object System.Management.Automation.RuntimeDefinedParameter("Site", [Microsoft.ActiveDirectory.Management.ADReplicationSite], $attributes)
        $parameters.Add("Site", $parameter)

        return $parameters
    }

    end {
        throw '{0}: StubNotImplemented' -f $MyInvocation.MyCommand
    }
}

The stub type ADReplicationSite looks like this.

    public class ADReplicationSite
    {
        // Constructor
        public ADReplicationSite() { }
        public ADReplicationSite(System.String identity) { }
        public ADReplicationSite(System.Guid guid) { }
        public ADReplicationSite(Microsoft.ActiveDirectory.Management.ADObject identity) { }
        public ADReplicationSite(Microsoft.ActiveDirectory.Management.ADDirectoryServer directoryServer) { }

        // Property
        public System.String DistinguishedName { get; set; }
        public System.String Name { get; set; }
        public System.String ObjectClass { get; set; }
        public System.Nullable<System.Guid> ObjectGuid { get; set; }
        public System.Collections.ICollection PropertyNames { get; set; }
        public System.Collections.Generic.ICollection<System.String> AddedProperties { get; set; }
        public System.Collections.Generic.ICollection<System.String> RemovedProperties { get; set; }
        public System.Collections.Generic.ICollection<System.String> ModifiedProperties { get; set; }
        public System.Int32 PropertyCount { get; set; }
        public Microsoft.ActiveDirectory.Management.ADPropertyValueCollection Item { get; set; }
    }

So the above assert failed because ToString() does not exist in the stub type, and $Site.Name does not contain the string value passed to the parameter Site, of the cmdlet Move-ADDirectoryServer, because there are no logic in the stub class ADReplicationSite` to handle that.

If I add logic to the class ADReplicationSite constructor that takes a string as argument, and change the test code to assert on $Site.Name then the assert works. I could have added the ToString() method to return the Site.Name property, but that is more uncertain if that is what the real ToString() method does.

Changed logic in the class ADReplicationSite. Just showing the relevant parts.

    public class ADReplicationSite
    {
        // Constructor
        ...
        public ADReplicationSite(System.String identity) { this.Name = identity; }
        ...

        // Property
        ...
        public System.String Name { get; set; }
        ...
    }

Changed logic in the assert in the test.

Assert-MockCalled -CommandName Move-ADDirectoryServer -Times 1 -ParameterFilter {
    $Site.Name -eq $correctSiteName
}
@johlju
Copy link
Contributor Author

johlju commented Apr 20, 2019

I don't think this one can be resolved? I thought I share my findings if someone else stumbles on the same problem, or if there are someone that can figure out a clever solution (other than manually change the code after the fact). 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant