Pester Mocking a script that varies output

Tagged: 

This topic contains 21 replies, has 4 voices, and was last updated by Profile photo of Anthony Anthony 1 month, 1 week ago.

Viewing 15 posts - 1 through 15 (of 22 total)
  • Author
    Posts
  • #50725
    Profile photo of Krishna Chaitanya
    Krishna Chaitanya
    Participant

    Hi all I have written a script to display the current user info, I would like to write Pester test case that should mock the output, also if I don't have return in the function how can I write a test for that too

    function Get-CurrentUserInfo
    {
    
        $domain = [Environment]::UserDomainName
        $user = [Environment]::UserName
        if (!([string]::IsNullOrEmpty($domain))) { $domain = $domain + '\' }
    
        $currentUser = $domain + $user
    
        #return $currentUser I have commented out so that it will not return any output
    }

    Here is my test case when there is return

    $here = Split-Path -Parent $MyInvocation.MyCommand.Path
    . "$here\Get-CurrentUserInfo.ps1"
    Describe "CurrentUser" {
        It "CurrentUser Info" {
            Get-CurrentUserInfo | Should be 'MY-PC\username'
        }
    }

    Which works fine with my PC but when I execute the same in other PC it will fail so how can I make it unique

    #50730
    Profile photo of Daniel Krebs
    Daniel Krebs
    Participant

    I would change the Should be 'MY-PC\username' to Should be "$($env:ComputerName)\$($env:UserName)" in your Pester test. That should get you around mocking the function in the first place.

    #50734
    Profile photo of Krishna Chaitanya
    Krishna Chaitanya
    Participant

    Hi Daniel can you give me the script I was just confused where to Mock it exactly

    #50740
    Profile photo of Daniel Krebs
    Daniel Krebs
    Participant

    For the example you've provided you don't really need to use mocking because you can just test for the correct value. If you mock a function you're not testing it because the mock function will be invoked instead.

    Example 1 (just test for the expected value)

    function Get-CurrentUserInfo
    {
    
        $domain = [Environment]::UserDomainName
        $user = [Environment]::UserName
        if (!([string]::IsNullOrEmpty($domain))) { $domain = $domain + '\' }
    
        $currentUser = $domain + $user
    
        return $currentUser
    }
    
    $here = Split-Path -Parent $MyInvocation.MyCommand.Path
    . "$here\Get-CurrentUserInfo.ps1"
    
    Describe "CurrentUser" {
        It "CurrentUser Info" {
            Get-CurrentUserInfo | Should be "$($env:UserDomainName)\$($env:UserName)"
        }
    }
    

    Example 2 (Get-CurrentUserInfo replaced by Mock function):

    $here = Split-Path -Parent $MyInvocation.MyCommand.Path
    . "$here\Get-CurrentUserInfo.ps1"
    
    Describe "CurrentUser" {
        It "CurrentUser Info" {
            Mock Get-CurrentUserInfo -MockWith { return 'Hello PowerShell' }
            Get-CurrentUserInfo | Should be 'Hello PowerShell'
        }
    }
    

    Your "Should Be" test doesn't need to reflect the actual output of the function because you can't just fake it because your original function is never being invoked.

    I hope above makes sense. If not, please let us know.

    • This reply was modified 1 month, 1 week ago by Profile photo of Daniel Krebs Daniel Krebs.
    #50753
    Profile photo of Krishna Chaitanya
    Krishna Chaitanya
    Participant

    Hi Daniel thanks for the code, but I am not able to debug my main function to see whats actually happening. If I save the file as .psm1 instead of .ps1 will the logic remains same or will it change

    #50755
    Profile photo of Daniel Krebs
    Daniel Krebs
    Participant

    Only the 2nd line of the test script changes to import your module into Pester session instead of dot-sourcing it.

    $here = Split-Path -Parent $MyInvocation.MyCommand.Path
    Import-Module "$here\Get-CurrentUserInfo.psm1" -Force
    
    Describe "CurrentUser" {
        It "CurrentUser Info" {
            Get-CurrentUserInfo | Should be "$($env:UserDomainName)\$($env:UserName)"
        }
    }
    
    #50757
    Profile photo of Krishna Chaitanya
    Krishna Chaitanya
    Participant

    That thing I got but coming to mocking will it be same?

    Import-Module "D:\MyFile.psm1" -Force
    Describe "My Test" {
        It "My Test" {
            Mock My-Function -MockWith { return 'Hello' }
            My-Function | Should be 'Hello'
        }
    }
    #50759
    Profile photo of Krishna Chaitanya
    Krishna Chaitanya
    Participant

    Also if my function is not returning any value how can I mock them

    #50773
    Profile photo of Daniel Krebs
    Daniel Krebs
    Participant

    Example (mock function without return value):

    Mock My-Function -MockWith {}
    
    #50775
    Profile photo of Daniel Krebs
    Daniel Krebs
    Participant

    To answer your other question. Yes, mocking will be the same if you import a module instead of dot-sourcing a script.

    #50777
    Profile photo of Krishna Chaitanya
    Krishna Chaitanya
    Participant

    Thanks Daniel but when I include Mock I am not able to hit the breakpoints to my actual solution any problem?

    #50779
    Profile photo of Anthony
    Anthony
    Participant

    Well no value returned should basically be a NULL so I would assume the following:

    Describe "My Test" {
        It "My Test" {
            Mock My-Function -MockWith { $null }
            My-Function | Should be $null
        }
    }

    Depending on how your module is written though you may need to look in to using inmodulescope https://github.com/pester/Pester/wiki/InModuleScope but for the most part mocking with a simple function being imported like that will work the same.

    #50781
    Profile photo of Krishna Chaitanya
    Krishna Chaitanya
    Participant

    Hi Anthony when I am using Mock, I am unable to hit the break point in my main module. I would like to view what my function is returning

    #50783
    Profile photo of Daniel Krebs
    Daniel Krebs
    Participant

    Krishna, that is correct. If you've mocked the function you're trying to test it will never be called.

    One wouldn't mock the function to be tested but any function being called by the function under test because you can't provide the correct environment or access to an external resource like a database or API.

    #50785
    Profile photo of Krishna Chaitanya
    Krishna Chaitanya
    Participant

    OK I have a script which creates a registry if it is 32 bit it will return respective path if not it will 64 bit path. I mocked that one and when I execute it I am not able to see the registry getting created.

Viewing 15 posts - 1 through 15 (of 22 total)

You must be logged in to reply to this topic.