Correct TestDrive usage

This topic contains 5 replies, has 2 voices, and was last updated by  Aleksandras Artemjevas 3 months, 4 weeks ago.

  • Author
    Posts
  • #69157

    Hello,
    I'm trying to test a script which stores some files on hard disk. During the test I would like to store a file to TestDrive:\ and check if it was indeed created. The problem is that file always gets created in "$env:TEMP\myfile.txt". Could you please explain what am I missing here?

    #script.ps1
    Function Get-FilePath {
        return "$env:TEMP\myfile.txt"
    }
    "Some Content" | Out-File (Get-FilePath)
    
    #script.Tests.ps1
    Describe "Script" {
        Function Get-FilePath {}
        Mock Get-FilePath { return "TestDrive:\myFile.txt" }
        . "$PSScriptRoot\Script.ps1"
        It "File should be created in TestDrive" {
            Test-Path (Get-FilePath) | Should Be $true
        }
        It "File should not be created in $env:Temp" {
            Test-Path "$env:TEMP\myfile.txt" | Should Be $false
        }
        if (Test-Path "$env:TEMP\myfile.txt") {
            Remove-Item "$env:TEMP\myfile.txt"
        } 
    }
    
  • #69169

    Adam Bertram
    Moderator

    You do not need to define Get-FilePath again in your test. The mock will take care of that. When you do that, your mock is applying to that function and not the one defined in your script.ps1 file.

  • #69172

    Hi Adam,
    Thanks for reply. If I'm not defining it, I get CommandNotFoundException and if I move script dot-source up, then it creates file in $env:temp and in It block it looks for file in TestDrive.

  • #69175

    Adam Bertram
    Moderator

    Ah. I see. This is where code refactoring comes into play. It seems like you're just testing if Get-FilePath returns what you expect it to since you don't have the actual file creation step inside of that function. If this is the case, I suggest remove the Out-File functionality from the script altogether and building a simple test to ensure that Get-FilePath returns the expected string like this:

    describe 'Get-FilePath' {
       $result = . $PSSscriptRoot\script.ps1
    
       it 'returns the temp file path' {
           $result | should be 'C:\Windows\Temp\myfile.txt'
       }
    }

    If you do need to confirm a function creates a file in a specific location you could also use a mock assertion to ensure Add-Content in this case used the expected path.

    script.ps1

    function New-File {
        param()
        Add-Content -Path "$env:TEMP\myfile.txt" -Value ''
    }

    Then the test would look like this:

    describe 'New-File' {
        mock 'Add-Content'
        . $PSScriptRoot\script.ps1
    
        it 'should create the file in the expected location' {
            Assert-MockCalled -CommandName 'Add-Content' -Times 1 -ParameterFilter { $Path -eq 'C:\Users\Adam\AppData\Local\Temp\myfile.txt' }
        }
    }
  • #69213

    For some reason my previous message was treated as spam. Just wanted to say thank you for help. Everything working smooth now.

  • #69181

    Heh, that makes sense. Ended up with this

    $settingsContent = @"
    #Spark Settings
    #Mon May 09 11:36:00 EEST 2016
    server=chat.runway.lv
    showOfflineUsers=false
    passwordSaved=false
    username=$env:USERNAME
    lastUpdateCheck=1460015572859
    autoLoginEnabled=false
    loginAsInvisibleEnabled=false
    offlineGroupVisible=true
    showEmptyGroups=false
    "@
    
    Function Get-SparkPropertiesFile {
        Write-Output (Join-Path $env:USERPROFILE "AppData\Roaming\Spark\spark.properties")
    }
    
    Function New-PropertiesFile {
        if (!(Test-Path (Split-Path (Get-SparkPropertiesFile))))
        {
            mkdir (Split-Path (Get-SparkPropertiesFile))
            try {
                Add-Content -Value $settingsContent -Path (Get-SparkPropertiesFile) -Encoding UTF8 -ErrorAction Stop
            } 
            catch {
                Write-Log -Message "Failed to create new properties file" -Level error -Path $env:gpLogfile
            }
            
        }
    }
    if (($env:gpObject -eq 'User') -and ($env:gpState -eq 'Logon')) {
        New-PropertiesFile
    } 
    
    $projectRoot = (get-item $PSScriptRoot).parent.parent.parent.FullName
    $ScriptsDir = "$projectRoot\GPScripts\Scripts"
    $scriptName = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '.Tests.ps1', ''
    
    
    Describe "User_Set-Spark" {
        $env:gpObject = 'User'
        $env:gpState = 'Logon'
    
        Mock 'Add-Content'
        . "$ScriptsDir\$scriptName\$scriptName.ps1"
        
        It "Should create new properties file" {
            Assert-MockCalled -CommandName 'Add-Content' -Times 1 -ParameterFilter { $Path -eq "$env:USERPROFILE\AppData\Roaming\Spark\spark.properties" }
        }
    }
    

    Thank you. Looking forward to your pester talk today. Cheers!

You must be logged in to reply to this topic.