";无法找到类型"";在Powershell单元测试中模拟类时



我正在创建一个模块,其中包含一个类文件和一个单元测试文件(Pester(。

类文件中的类B继承自另一个模块中的类A

如果我试图运行一个单元测试,通过继承类B来模拟它,我会得到"Unable to find type [B]"

但是,如果我只是实例化类B,那么一切都可以。

既然我可以实例化它,为什么我不能从类继承?

单元测试文件:

using module ".MyModule.psd1" 
BeforeAll {
Import-Module $PSScriptRootMyModule.psd1 -Force
}
Describe 'My unit test 1' {
It 'Runs unit test 1' {

# Mock a private function
# Gives: Unable to find type [B].
class MockedClassB : B
{
MockedClassB ([int]$foo) : base($foo)
{
}
[string] MyMethod() { return 'MockedString' }
}
$mockedB = [MockedClassB]::new(13)
$mockedB.Run()   
}
}

Describe 'My unit test 2' {
It 'Runs unit test 2' {

# No errors.
$instanceB = [B]::new(13)
$instanceB.Run()   
}
}

MyModule.psd1:

@{
RootModule = 'Include.psm1'
ModuleVersion = '1.0.0'
# This is needed to use classes. Otherwise the Test file will give "Unable to find type"
ScriptsToProcess = @(
'ClassesB.ps1'
)

RequiredModules = ''
# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
FunctionsToExport = @() 
# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
CmdletsToExport = @()
# Variables to export from this module
# VariablesToExport = '*'
# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
AliasesToExport = @()
}

包含.psm1:

#Requires -Version 5.0
[cmdletbinding()]
param()
Write-Verbose $PSScriptRoot
Write-Verbose 'Import Classes in order because of dependencies'
$classList = @(
'B'
)
foreach($class in $classList)
{
Write-Verbose " Class: $class"
. "$psscriptrootClasses$class.ps1"
}

B.ps1:

using module ".....ModuleContainingClassAModuleContainingClassA.psd1"
class B: A
{
# ctor
B([int]$foo)
{
}
}

[编辑]如果我替换模块文件Include.psm1中类的点Include,而只是让它包含类定义,那么错误就会消失。

我在这里也发现了一个类似的问题,但没有任何公认的答案:使用Pester 5和PowerShell 7 模拟类函数

如果using module语句嵌入到Here String中并用InModuleScope -ScriptBlock调用,这是可能的,如下所示:

# InModuleScope is needed when using classes to prevent 'Unable to find type'
InModuleScope MyModule {
Describe 'My unit test 1' {
BeforeAll {
<# Mock a private method
Must use a Here-String because we need to pass 'using' which must be first in a scriptblock, but if it is outside the here-string then
PowerShell will fail to parse the test script with 'Unable to find type [NameOfClass]'.
Also, the whole thing must be inside InModuleScope as usual when dealing with classes.
#>
$inModuleScopeScriptBlock = @'
using module ".MyModule.psd1"
class MockedClassB : B
{
MockedClassB ([int]$foo) : base($foo)
{
}
[string] MyMethod() { return 'MockedString' }
}
$script:mockedB = [MockedClassB]::new(13)
'@
InModuleScope -ModuleName MyModule -ScriptBlock ([Scriptblock]::Create($inModuleScopeScriptBlock))


}
It 'Runs unit test 1' {
$mockedB.Run()            
}
}

最新更新