tests/Import-ModuleFromPath.Tests.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#Requires -Modules Pester
. $PSScriptRoot\TestHelper.ps1

$module = 'testing'
$sut = 'Import-ModuleFromPath'

$path = Split-Path -Path $PSScriptRoot -Parent
Get-Module -Name $module -All | Remove-Module -Force
Import-Module $path -Force -ErrorAction Stop


Describe "'$sut' tests with valid module folder" {

    $modulePath = New-TestModule 'mymodule'

    Mock -CommandName Remove-Module -ModuleName $module -MockWith { }
    Mock -CommandName Import-Module -ModuleName $module -MockWith { }

    It "should not throw error" {
        { & $sut -Path $modulePath } | Should Not Throw
    }
    
    Context "With loaded module" {

        # Simulate module has already been loaded
        Mock -CommandName Get-Module -ModuleName $module -MockWith { 
            New-Object -TypeName PSModuleInfo -ArgumentList $false 
        }

        & $sut -Path $modulePath
        
        It "Remove-Module should be called" {
            Assert-MockCalled -CommandName Remove-Module -Exactly 1 -ModuleName $module -Scope Context
        }

        It "Import-Module should be called" {           
            Assert-MockCalled -CommandName Import-Module -Exactly 1 -ModuleName $module -Scope Context
        }
    }

    Context "With module not loaded" {

        # Simulate no module has been loaded
        Mock -CommandName Get-Module -ModuleName $module -MockWith { }
        
        & $sut -Path $modulePath
        
        It "Remove-Module should not be called" {
            Assert-MockCalled -CommandName Remove-Module -Exactly 0 -ModuleName $module -Scope Context
        }

        It "Import-Module should be called" {
            Assert-MockCalled -CommandName Import-Module -Exactly 1 -ModuleName $module -Scope Context
        }
    }
}

Describe "'$sut' tests with no corresponding psm1 file" {
    
    # Only create folder without module file
    $modulePath = New-Item -Path "${TestDrive}\module" -ItemType Directory

    Mock -CommandName Remove-Module -ModuleName $module -MockWith { }
    Mock -CommandName Get-Module -ModuleName $module -MockWith { }

    It "should throw error" {
        { & $sut -Path $modulePath } | Should Throw
    }
}

Describe "'$sut' tests with invalid path" {
    
    $modulePath = "C:\path\does\not\exist"

    It "Should not exist the module" {
        $modulePath | Should not exist
    }

    It "should throw error" {
        { & $sut -Path $modulePath } | Should Throw
    }
}

<#
    Idea of the following tests:
    When the SUT gets invoked without a Path parameter using the Parent switch,
    the Path gets determinded by analyzing the PSCallStack. To get a valid CallStack
    the invocation of the SUT gets written into a *.ps1 file on the $TestDrive.
    The created *.ps1 file will be used to call the SUT.
#>

Describe "'$sut' with Parent switch" {

    $modulePath = New-TestModule 'mymodule'
    # Create the file as it would be a pester tests file and write the file content into it
    $scriptPath = New-TestScript `
        -Path "${modulePath}\tests\Invoke-SutWithoutPath.Tests.ps1" `
        -Content "$sut -Parent"
    
    Mock -CommandName Remove-Module -ModuleName $module -MockWith { }
    Mock -CommandName Import-Module -ModuleName $module -MockWith { }
    Mock -CommandName Get-Module -ModuleName $module -MockWith { }

    It "Should exist the test script" {
        $scriptPath | Should exist
    }

    It "should identify the path when location is set" {
        # invoke the command from the created script
        & $scriptPath  
        Assert-MockCalled -CommandName Import-Module -Exactly 1 `
            -ModuleName $module -Scope It -ParameterFilter { $Name -eq $modulePath}
    }
}

Describe "'$sut' with real module structure" {

    $modulePath = New-TestModule 'mymodule'

    AfterEach {
        Get-Module 'mymodule' -All | Remove-Module
    }

    Context "Calling $sut from tests script using absolute path" {

        $scriptPath = New-TestScript -Path "${modulePath}\Some.Tests.ps1" `
            -Content "$sut $modulePath"

        It "should load module" {
            & $scriptPath
            Get-Module 'mymodule' -All | Should not BeNullOrEmpty
        }
    }
    
    Context "Calling $sut using relative path" {
        
        $currentLocation = Get-Location
        
        It "should load module when at correct location" {
            Set-Location -Path $modulePath
            & $sut ..\mymodule
            Get-Module 'mymodule' -All | Should not BeNullOrEmpty
        }

        It "should throw when at wrong location" {
            Set-Location -Path (Split-Path $modulePath -Parent)
            { & $sut ..\mymodule } | Should throw
        }

        Set-Location $currentLocation
    }

    Context "Calling $sut using '.' for Path parameter" {

        $currentLocation = Get-Location

        It "should load module" {
            Set-Location -Path $modulePath
            & $sut .
            Get-Module 'mymodule' -All | Should not BeNullOrEmpty
        }

        Set-Location $currentLocation
    }
}