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

How to test for ShouldProcess and Confirm? #9

Closed
thomykay opened this issue Sep 12, 2013 · 3 comments
Closed

How to test for ShouldProcess and Confirm? #9

thomykay opened this issue Sep 12, 2013 · 3 comments

Comments

@thomykay
Copy link

Any idea how to test for ShouldProcess and Confirm support using PSate? The whatif output can be checked with Should, but how to test Confirm?

@jonwagner
Copy link
Owner

That's a tough one.

I assume you have a function like this:

function Test {
    [CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param()
    process {
        if ($PSCmdlet.ShouldProcess("test")) {
            "Doing it"
        }
    }
}

Test

If you're writing a dangerous action, you probably want to write tests like:

  • If confirm is true and the user hits cancel, the action is not performed
  • If confirm is true and the user hits ok, the action is performed

In this case, you want to control the output of $PSCmdlet.ShouldProcess. I think the easiest way to do this is to create another function called CheckShouldProcess that just calls $PSCmdlet.ShouldProcess. Then you can use PSMock to mock the function and control the outputs. Something like this:

Enable-Mock | iex

function CheckShouldProcess {
    param (
        $target
    ) 
    $PSCmdlet.ShouldProcess($target)
}

function Test2 {
    [CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param()
    process {
        if (CheckShouldProcess("test")) {
            "Doing it"
        }
    }
}

Mock CheckShouldProcess { $false }
Test2  # no prompt and does not perform the action
Mock CheckShouldProcess { $true }
Test2  # no prompt and performs the action
Clear-Mocks
Test2  # prompts for a response

It might also be possible to replace $PSCmdlet with a new PSObject where you control the ShouldProcess method, but since $PSCmdlet is an automatic variable, it probably wouldn't be too easy.

@thomykay
Copy link
Author

Indeed, mocking (the whole) $PSCmdlet variable seems to be a bit hard and might also interfere with other code using it.

Thanks for your thoughts on this. Very helpful.

In general: I've used the PSate, PShould combination for some days now and I really like it. Eventually it's fun to write tests for PowerShell modules.

@jonwagner
Copy link
Owner

Also, if you have more advanced testing scenarios, you can use parameters in the Mock:

Mock CheckShouldProcess { param ($target) { if ($target == "foo") return $true; else return $false;  } }

Enjoy.

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

2 participants