在.ps1脚本中模拟一个函数

时间:2016-05-17 14:07:41

标签: unit-testing powershell pester

我有一个PowerShell .ps1文件,其中包含脚本顶部的函数,后跟调用这些函数的不同命令。我正在使用Pester对我的脚本文件进行单元测试。

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

我试过嘲笑这个函数,但是我得到一个错误,说'#34;找不到命令"。

我也试过添加一个空的"虚拟"在describe块中的函数。这并没有给我上述错误,但它没有正确地模拟脚本中的函数。

我有两个文件。一个用于保存测试,另一个用于保存函数和调用函数。以下是两个例子:

File1.ps1

 /// <summary>
        /// gets the published levels
        /// </summary>
        /// <param name="subModuleID"></param>
        /// <param name="parentId"></param>
        /// <returns>List of published levels</returns>
        [System.Web.Http.AcceptVerbs("GET")]
        [System.Web.Http.HttpGet]
        [ActionName("GetAllPublishedLevel")]

        public List<OMLevelsBALDTO> GetAllPublishedLevel(int submoduleId, int? parentId)
        {
            return businessprovider.GetAllPublishedLevel(submoduleId,parentId);
        }

File2.Tests.ps1

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

Backup-Directory $true

1 个答案:

答案 0 :(得分:4)

我不认为这是可能的。至少对你当前的实现。我不久前问了同样的问题...... Pester Issue 414

但是你可以将内部函数拆分到同一目录中的另一个脚本文件中,以便进行单元测试和模拟。您只需要在主脚本文件中点源该函数即可使用它:

Main-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"
}

Inner-Function.ps1:

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

Main-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
    }
}

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

Inner-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
    }

主要功能中的Dot Sourcing依赖功能以及单元测试文件... . "$moduleRoot\Inner-Function.ps1"

Split-Path -Path $MyInvocation.MyCommand.Path在用户会话中为$null,但在执行上下文中调用时不会为$null。意思是,您可以在C:\users\nhudacin中并仍然正确加载此脚本/模块。否则,您必须始终在与其所在位置相同的目录中执行此脚本/模块,而不使用$MyInvoation变量。