-
-
Notifications
You must be signed in to change notification settings - Fork 468
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
v5: InModuleScope fails to pass values from the current scope without explicit -Parameters #1603
Comments
@vexx32 are you sure that test worked in v4? Because the $Pattern would be defined in script session state, while the ScriptBlock would be invokes in module scope. Can you put breakpoint on the This shows that $Pattern is null, in v4, as expected: Get-Module PSKoans | Remove-Module
New-Module -name PSKoans -scriptblock { function ConvertFrom-WildcardPattern ($Pattern) { Write-Host $Pattern ; $Pattern } } -PassThru | Import-Module
describe 'a' {
It 'replaces wildcard characters with regex equivalent' -TestCases @(
@{ Pattern = 'About*son'; Expected = '^About.*son$' }
@{ Pattern = 'AboutArrays*'; Expected = '^AboutArrays' }
@{ Pattern = '*Arrays'; Expected = 'Arrays$' }
@{ Pattern = '*Array*'; Expected = 'Array' }
) {
param ($Pattern, $Expected)
InModuleScope 'PSKoans' {
ConvertFrom-WildcardPattern $Pattern
} | Should -Be $Expected
}} Is maybe the whole test running in PSKoans module? |
🤔 oh, huh! Yeah, come to think of it, I think I probably had the entire test file here running in module scope. Was trying to avoid that this time around. So for this kind of thing I do need to explicitly insert parameters? |
Yes for this you should be forced to pass params explictly via the -Parameters parameter, because you are crossing a session state boundary. But you should not be forced to specify the param block, which does not work at the moment. So needing to specify the param block manually is a bug. The other thing is not. |
That makes sense, thanks! |
Please forgive the slight issue hijack, but I have a related question. In @vexx32's example that does work, is there any way to use variables that were defined outside of the TestCases array definition within the array? I have some expensive-to-initialize test data that I'm trying to assign to a variable in a BeforeAll block and then insert it into the TestCases array definition. But all I get is In other words: Describe 'a' {
BeforeAll {
$expensive = Get-ExpensiveData
}
It 'Does stuff' -TestCases @(
@{ thing1 = 'blah1'; thing2 = $expensive }
@{ thing2 = 'blah2'; thing2 = $expensive }
@{ thing3 = 'blah3'; thing2 = $expensive }
) {
InModuleScope MyModule -Parameters @{thing1=$thing1;thing2=$thing2} {
param($thing1,$thing2)
Invoke-Stuff $thing1, $thing2 | Should -Be 'blah'
}
}
} All of the thing2 instances end up as $null within the test. If I just run The other thing I've considered doing as sort of a hacky workaround is defining an empty private function within my module that I can mock specifically to pass data into the module scope from outside the module scope. |
Yes, but you'd put that code outside of BeforeAll. Or in Pester 5.1.0-beta1 and newer, into BeforeDiscovery block. This will define them during discovery and you can then pass them to the tests using testcases as you are doing just now. It will also run just once. |
Oh sweet. For some reason, I thought all initialization stuff had to occur in a Before* block now. |
-TestCases and other things that happen outside a Before* or It block are a completely separate step now, so if you want to do setup for -TestCases they need to be out of those blocks or in the BeforeDiscovery block as @nohwnd mentioned. You can't directly mix -TestCases with stuff that happens in a Before* block though, you'd have to pull those values in as variables inside the It block directly rather than with -TestCases. |
@nohwnd resurrecting this issue, currently this is what is required to work: It 'has the mandatory value of parameter "<Name>" set to "<Mandatory>"' -TestCases @(
@{Name = 'Name'; Mandatory = $False }
@{Name = 'VaultName'; Mandatory = $False }
@{Name = 'AdditionalParameters'; Mandatory = $False }
) {
InModuleScope 'SecretManagement.KeePass.Extension' -Parameters @{Name=$Name; Mandatory=$Mandatory} {
param($Name,$Mandatory)
$testAttribute = ((Get-Command -Module $ExtModuleName -Name $FunctionName).Parameters[$Name].Attributes
| Where-Object {$PSItem -is [System.Management.Automation.ParameterAttribute]}).Mandatory
$testAttribute | Should -Be $Mandatory
}
} In my opinion this is too much boilerplate when testcases exist. I would propose the following solution:
The end result being that this would work: It 'has the mandatory value of parameter "<Name>" set to "<Mandatory>"' -TestCases @(
@{Name = 'Name'; Mandatory = $False }
@{Name = 'VaultName'; Mandatory = $False }
@{Name = 'AdditionalParameters'; Mandatory = $False }
) {
InModuleScope 'SecretManagement.KeePass.Extension' {
$testAttribute = ((Get-Command -Module $ExtModuleName -Name $FunctionName).Parameters[$Name].Attributes
| Where-Object {$PSItem -is [System.Management.Automation.ParameterAttribute]}).Mandatory
$testAttribute | Should -Be $Mandatory
}
} |
@JustinGrote The testcase hashtable is already available as It 'has the mandatory value of parameter "<Name>" set to "<Mandatory>"' -TestCases @(
@{Name = 'VaultName'; Mandatory = $False }
) {
InModuleScope 'SecretManagement.KeePass.Extension' -Parameters $_ {
$Name | Should -Be 'VaultName'
$Mandatory | Should -Be $False
}
}
|
@fflaten the |
1. General summary of the issue
In V4, this worked:
My attempt at converting to V5 was:
This does not work. The following does work:
Also... it seems
-ArgumentList
does not work either. I tried this way with no success:2. Describe Your Environment
3. Expected Behavior
InModuleScope
shouldn't require explicit parameter passing.4.Current Behavior
InModuleScope
requires explicit passing of parameters as a hashtable; even-ArgumentList
doesn't work.5. Possible Solution
6. Context
Converting module tests to v5. 🙂
The text was updated successfully, but these errors were encountered: