2016-05-17 78 views
2

我有一个PowerShell .ps1文件,其中包含脚本顶部的函数,随后是调用这些函数的不同命令。我正在使用Pester来测试我的脚本文件。在ps1脚本中模拟一个函数

如何模拟PowerShell .ps1脚本中的函数?

我试过嘲笑函数,但得到一个错误说“找不到命令”。

我也尝试在describe块中添加一个空的“dummy”函数。这不会给我上面的错误,但它不会正确地模拟脚本中的函数。

我有两个文件。一个持有测试,另一个持有功能和调用功能。下面是两个例子:

File1.ps1

Function Backup-Directory([switch]$IsError) 
{ 
    If($IsError) 
    { 
     Write-Error "Error" 
     Exit 1 
    } 
} 

Backup-Directory $true 

File2.Tests.ps1

$here = (Split-Path -Parent $MyInvocation.MyCommand.Path) -replace '\\test', '\main' 
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.', '.' 
$productionFile = "$here\$sut" 

Describe "File1" { 

    Context "When the Back-Directory outputs an error." { 

     # Arrange 
     Mock Back-Directory { } 
     Mock Write-Error 

     # Act 
     & $productionFile 
     $hasSucceeded = $? 

     # Assert 
     It "Calls Backup-Directory" { 
      Assert-MockCalled Backup-Directory -Exactly 1 -ParameterFilter { 
       $IsError -eq $true 
      } 
     } 

     It "Writes error message." { 
      Assert-MockCalled Write-Error -Exactly 1 -ParameterFilter { 
       $Message -eq "Error" 
      } 
     } 

     It "Exits with an error." { 
      $hasSucceeded | Should be $false 
     } 
    } 
} 
+0

我们至少需要更多的信息,可能还需要查看代码。您想要模拟的功能与您使用pester测试的同一个文件中? – EBGreen

回答

4

我不认为这是可能的。至少在你目前的实施中。我问了一会儿同样的问题...... Pester Issue 414

但是你可以将内部函数分割到同一目录中的另一个脚本文件中,允许你单元测试和模拟它。你只需要点源的功能在你的主脚本文件,以便能够使用它:

主Function.ps1:

# Main script 
function Main-Function { 
    # if debugging, set moduleRoot to current directory 
    if ($MyInvocation.MyCommand.Path) { 
     $moduleRoot = Split-Path -Path $MyInvocation.MyCommand.Path 
    }else { 
     $moduleRoot = $PWD.Path 
    } 

    # dot source the inner function 
    . "$moduleRoot\Inner-Function.ps1" 

    Write-Output "This is the main script. Calling the inner function" 

    Inner-Function 

    Write-Output "Back in the main script" 
} 

内Function.ps1:

function Inner-Function { 
    Write-Output "This is the inner function" 
} 

主Function.Tests.ps1:

$moduleRoot = Split-Path -Parent $MyInvocation.MyCommand.Path 

# Load Testing Function 
. "$moduleRoot\Main-Function.ps1" 

# Load Supporting Functions 
. "$moduleRoot\Inner-Function.ps1" 

Describe 'Main Script' { 
    Mock Inner-Function { return "This is a mocked function" } 

    It 'uses the mocked function' { 
     (Main-Function -match "This is a mocked function") | Should Be $true 
    } 
} 

这是一个非常好的做法,因为我们可以单元测试内FUNC随着逻辑的增长,向它添加测试是非常容易的(并且可以与其他脚本/函数隔离开来)。

内Functions.Tests.ps1:

$moduleRoot = Split-Path -Parent $MyInvocation.MyCommand.Path 

# Load Testing Function 
. "$moduleRoot\Inner-Function.ps1" 

Describe 'Inner Function' { 
    It 'outputs some text' { 
     Inner-Function | Should Be "This is the inner function" 
    } 
} 

这里有两个要点...

寻找相关的功能定位,无论您当前执行目录的...

if ($MyInvocation.MyCommand.Path) { 
     $moduleRoot = Split-Path -Path $MyInvocation.MyCommand.Path 
    }else { 
     $moduleRoot = $PWD.Path 
    } 

AND

在主函数中点源依赖函数以及单元测试文件... . "$moduleRoot\Inner-Function.ps1"

Split-Path -Path $MyInvocation.MyCommand.Path是在用户会话$null,但是从执行上下文中调用时,不会$null。意思是说,你可能在C:\users\nhudacin并且仍然正确加载这个脚本/模块。否则,您必须始终在不使用$MyInvoation变量的情况下,从它所在的相同目录内执行此脚本/模块。

相关问题