PowerShell/test/powershell/Language/Classes/Scripting.Classes.StaticMethod.Tests.ps1

123 lines
5 KiB
PowerShell

# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
Describe "Additional static method tests" -Tags "CI" {
Context "Basic static member methods" {
BeforeAll {
function Get-Name { "YES" }
}
It "test basic static constructor" {
class Foo {
static [string] $Name
static Foo() { [Foo]::Name = Get-Name }
}
[Foo]::Name | Should -Be "Yes"
}
It "test basic static method" {
class Foo {
static [string] GetName() { return (Get-Name) }
}
[Foo]::GetName() | Should -Be "Yes"
}
}
Context "Class defined in different Runspace" {
BeforeAll {
@'
class Foo
{
static [string] $Name
static Foo() { [Foo]::Name = Get-Name }
static [string] GetName()
{
return (Get-AnotherName)
}
}
'@ | Set-Content -Path $TestDrive\class.ps1 -Force
## Define the functions that [Foo] depends on in the default Runspace.
function Get-Name { "Default Runspace - Name" }
function Get-AnotherName { "Default Runspace - AnotherName" }
## Create another Runspace PS1
$ps1 = [powershell]::Create()
## Create another Runspace PS2
$ps2 = [powershell]::Create()
function RunScriptInPS {
param(
[powershell] $PowerShell,
[string] $Script,
[switch] $IgnoreResult
)
$result = $PowerShell.AddScript($Script).Invoke()
$PowerShell.Commands.Clear()
if (-not $IgnoreResult) {
return $result
}
}
## Define the functions that [Foo] depends on in PS1 Runspace.
RunScriptInPS -PowerShell $ps1 -Script "function Get-Name { 'PS1 Runspace - Name' }" -IgnoreResult
RunScriptInPS -PowerShell $ps1 -Script "function Get-AnotherName { 'PS1 Runspace - AnotherName' }" -IgnoreResult
# Dot source class.ps1 in the current Runspace
. $TestDrive\class.ps1
# And then dot source class.ps1 in the PS1 Runspace
RunScriptInPS -PowerShell $ps1 -Script ". $TestDrive\class.ps1" -IgnoreResult
}
AfterAll {
# Dispose both Runspaces
$ps1.Dispose()
$ps2.Dispose()
}
It "Static constructor should run in the triggering Runspace if the class has been defined in that Runspace" {
## The static constructor is triggered by accessing '[Foo]::Name' which happens in the current Runspace.
## The class 'Foo' has been defined in the current Runspace, so it uses the current Runspace to run the
## static constructor.
[Foo]::Name | Should -BeExactly "Default Runspace - Name"
## Static constructor runs only once, so accessing the Name property in the PS1 Runspace will just return
## the existing value.
RunScriptInPS -PowerShell $ps1 -Script "[Foo]::Name" | Should -BeExactly "Default Runspace - Name"
}
It "Static method use the Runspace where the call happens if the class has been defined in that Runspace" {
## We call the static method in the current Runspace. The class 'Foo' has been defined
## in the current Runspace, so it will use it to run the method.
[Foo]::GetName() | Should -BeExactly "Default Runspace - AnotherName"
## We call the static method in PS1 Runspace. The class 'Foo' has been defined in the
## PS1 Runspace, so it will use it to run the method.
RunScriptInPS -PowerShell $ps1 -Script "[Foo]::GetName()" | Should -BeExactly 'PS1 Runspace - AnotherName'
}
It "Static method use the default SessionState if it's called in a Runspace where the class is not defined" {
## Define the functions that [Foo] depends on in PS2 Runspace.
RunScriptInPS -PowerShell $ps2 -Script "function Get-Name { 'PS2 Runspace - Name' }" -IgnoreResult
RunScriptInPS -PowerShell $ps2 -Script "function Get-AnotherName { 'PS2 Runspace - AnotherName' }" -IgnoreResult
## Define the function to call the static method 'GetName' on the passed-in type
RunScriptInPS -PowerShell $ps2 -Script 'function Call-GetName([type] $type) { $type::GetName() }' -IgnoreResult
## We call the static method in PS2 Runspace. The class is not defined in this Runspace,
## so the default SessionState will be used to run the method. The default SessionState
## is always the one where the class was defined most recently. In this case, the class
## was lastly defined in PS1 Runspace, os the method will be invoked in PS1 Runspace.
$result = $ps2.AddCommand("Call-GetName").AddParameter("type", [Foo]).Invoke()
$result | Should -BeExactly 'PS1 Runspace - AnotherName'
}
}
}