Permalink
Browse files

mock works with any command (not just functions) and the parameter fi…

…lters are implemented. also implemented Clear-Mock
  • Loading branch information...
1 parent 9f39761 commit ec77ceab7ba99bec93376ad6ca1f6f2d5dfc9d22 @mwrock mwrock committed Oct 16, 2012
Showing with 83 additions and 8 deletions.
  1. +48 −2 Functions/Mock.Tests.ps1
  2. +35 −6 Functions/Mock.ps1
@@ -2,7 +2,7 @@ $here = Split-Path -Parent $MyInvocation.MyCommand.Path
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path).Replace(".Tests.", ".")
. "$here\$sut"
-function FunctionUnderTest {
+function FunctionUnderTest ([string]$param1=""){
return "I am a real world test"
}
@@ -19,8 +19,31 @@ Describe "When calling Mock on existing function" {
It "Should Invoke the mocked script" {
$result.should.be("I am the mock test")
}
+ Clear-Mocks
}
+Describe "When calling Mock on existing cmdlet" {
+ Mock Get-Process {return "I am not Get-Process"}
+
+ $result=Get-Process
+
+ It "Should Invoke the mocked script" {
+ $result.should.be("I am not Get-Process")
+ }
+ Clear-Mocks
+}
+
+Describe "When calling Mock on cmdlet Used by Mock" {
+ Mock Invoke-Command {return "I am not Invoke-Command"}
+ $result = Invoke-Command {return "yes I am"}
+
+ It "Should Invoke the mocked script" {
+ $result.should.be("I am not Invoke-Command")
+ }
+ Clear-Mocks
+}
+
+
Describe "When calling Mock on non-existing function" {
try{
Mock NotFunctionUnderTest {return}
@@ -29,6 +52,29 @@ Describe "When calling Mock on non-existing function" {
}
It "Should throw correct error" {
- $result.Exception.Message.should.be("Could not find function NotFunctionUnderTest")
+ $result.Exception.Message.should.be("Could not find command NotFunctionUnderTest")
+ }
+ Clear-Mocks
+}
+
+Describe "When calling Mock on existing function without matching params" {
+ Mock FunctionUnderTest {return "fake results"} -parameterFilter {$param1 -eq "test"}
+
+ $result=FunctionUnderTest "badTest"
+
+ It "Should redirect to real function" {
+ $result.should.be("I am a real world test")
+ }
+ Clear-Mocks
+}
+
+Describe "When calling Mock on existing function with matching params" {
+ Mock FunctionUnderTest {return "fake results"} -parameterFilter {$param1 -eq "badTest"}
+
+ $result=FunctionUnderTest "badTest"
+
+ It "Should return mocked result" {
+ $result.should.be("fake results")
}
+ Clear-Mocks
}
View
@@ -1,10 +1,24 @@
-function Mock ([string]$function, [ScriptBlock]$mockWith, [switch]$verifiable, [HashTable]$parameterFilters = @{})
+$mockTable = @{}
+
+function Mock ([string]$commandName, [ScriptBlock]$mockWith, [switch]$verifiable, [ScriptBlock]$parameterFilter = {$True})
{
# If verifiable, add to a verifiable hashtable
- if(!(Test-Path Function:\$function)){ Throw "Could not find function $function"}
- Rename-Item Function:\$function script:PesterIsMocking_$function
- Set-Item Function:\script:$function -value $mockWith
- # Mocked function should redirect to real function if param filters are not met
+ $origCommand = (Get-Command $commandName -ErrorAction SilentlyContinue)
+ if(!$origCommand){ Throw "Could not find Command $commandName"}
+ $blocks = @{Mock=$mockWith; Filter=$parameterFilter}
+ $mock = $mockTable.$commandName
+ if(!$mock) {
+ if($origCommand.CommandType -eq "Function") {
+ Rename-Item Function:\$commandName script:PesterIsMocking_$commandName
+ }
+ $metadata=New-Object System.Management.Automation.CommandMetaData $origCommand
+ $cmdLetBinding = [Management.Automation.ProxyCommand]::GetCmdletBindingAttribute($metadata)
+ $params = [Management.Automation.ProxyCommand]::GetParamBlock($metadata)
+ $newContent=Get-Content function:\MockPrototype
+ Set-Item Function:\script:$commandName -value "$cmdLetBinding `r`n param ( $params ) `r`n$newContent"
+ $mock=@{OriginalCommand=$origCommand;blocks=@($blocks)}
+ } else {$mock.blocks += $blocks}
+ $mockTable.$commandName = $mock
# param filters are met, mark in the verifiable table
}
@@ -16,5 +30,20 @@ function Assert-VerifiableMocks {
function Clear-Mocks {
# Called at the end of Describe
# Clears the Verifiable table
- # Renames all renamed mocks back to original names
+ $mockTable.Keys | % { Microsoft.PowerShell.Management\Remove-Item function:\$_ }
+ $script:mockTable = @{}
+ Microsoft.PowerShell.Management\Get-ChildItem Function: | ? { $_.Name.StartsWith("PesterIsMocking_") } | % {Microsoft.PowerShell.Management\Rename-Item Function:\$_ "script:$($_.Name.Replace('PesterIsMocking_', ''))"}
+}
+
+function MockPrototype {
+ $functionName = $MyInvocation.MyCommand.Name
+ $mock=$mockTable.$functionName
+ $idx=$mock.blocks.Length
+ while(--$idx -ge 0) {
+ if(Microsoft.PowerShell.Core\Invoke-Command $mock.blocks[$idx].Filter) {
+ Microsoft.PowerShell.Core\Invoke-Command $mockTable.$functionName.blocks.mock
+ return
+ }
+ }
+ &($mock.OriginalCommand)
}

0 comments on commit ec77cea

Please sign in to comment.