You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell单元测试Mock类时提示‘无法找到类型[B]’的问题

PowerShell模块类继承Mock问题解析

问题描述

创建包含类与Pester单元测试的模块,类B继承自外部模块的类A。单元测试中直接实例化类B可正常运行,但尝试通过继承类B创建Mock类时,报错Unable to find type [B]。

相关代码文件如下:

单元测试文件

using module ".\MyModule.psd1" 

BeforeAll {
    Import-Module $PSScriptRoot\MyModule.psd1 -Force
}

Describe 'My unit test 1' {
    It 'Runs unit test 1' {
            
            # 报错: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' {
        
        # 无错误
        $instanceB = [B]::new(13)
        $instanceB.Run()   
    }
}

MyModule.psd1

@{
RootModule = 'Include.psm1'
ModuleVersion = '1.0.0'

# 用于加载类,否则测试文件会报"无法找到类型"
ScriptsToProcess = @(
      'Classes\B.ps1'
   )


RequiredModules = ''

FunctionsToExport = @() 
CmdletsToExport = @()
AliasesToExport = @()

}

Include.psm1

#Requires -Version 5.0
[cmdletbinding()]
param()

Write-Verbose $PSScriptRoot
Write-Verbose '按依赖顺序导入类'
$classList = @(
    'B'
)

foreach($class in $classList)
{
    Write-Verbose " 类: $class"
    . "$psscriptroot\Classes\$class.ps1"
}

B.ps1

using module ".\..\..\ModuleContainingClassA\ModuleContainingClassA.psd1"

class B: A
{
    # 构造函数
    B([int]$foo)
    {
    }
}

补充信息:若将Include.psm1中点源加载类的方式替换为直接在该文件中定义类,错误会消失。

原因分析

  1. 模块类的可见性限制:PowerShell模块默认不会导出类,除非在模块清单(psd1)中通过TypesToExport明确指定。虽然ScriptsToProcess会将类加载到全局作用域,允许直接实例化,但在Pester的It块作用域中定义子类时,PowerShell需要父类B的定义具备可继承的可见性——仅仅能实例化不足以满足继承的类型解析要求。

  2. 重复加载导致的作用域冲突:当前模块同时通过ScriptsToProcess和Include.psm1点源加载B.ps1,造成类B被重复定义在不同作用域(全局+模块私有),进一步干扰了类型解析逻辑,导致继承时无法正确找到类B的定义。

解决方案

方案1:明确导出模块中的类

修改MyModule.psd1,添加TypesToExport配置,将类B导出到模块外部作用域:

@{
RootModule = 'Include.psm1'
ModuleVersion = '1.0.0'

ScriptsToProcess = @(
      'Classes\B.ps1'
   )

RequiredModules = ''

FunctionsToExport = @() 
CmdletsToExport = @()
AliasesToExport = @()
# 添加此行导出类B
TypesToExport = @('B')
}

方案2:移除重复的类加载逻辑

保留一种类加载方式即可,避免重复定义:

  • 要么删除ScriptsToProcess配置,仅通过Include.psm1点源加载类;
  • 要么删除Include.psm1中的点源加载代码,仅依赖ScriptsToProcess加载类B。

方案3:在Pester中确保类的可见性

在BeforeAll块中使用using module替代Import-Module,确保类定义在测试作用域中正确解析:

BeforeAll {
    using module $PSScriptRoot\MyModule.psd1
}

内容的提问来源于stack exchange,提问作者Rye bread

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 02:10:57