Should-* assertions (v6)
Overview​
Pester includes a comprehensive set of assertions that you can use to either fail or pass a test. In fact, Pester v6 includes two sets of assertions:
- The new
Should-*assertions introduced in Pester v6 (note the hyphen, no space), e.g.Should-Be,Should-BeString,Should-BeTrue. These are the recommended way to assert in v6 and are the focus of this page. - The classic
Shouldcommand known from previous versions of Pester, invoked using parameter sets likeShould -Be,Should -BeTrue. This is the older syntax and is documented separately in the Classic assertions (v5).
Both styles are supported side-by-side in Pester v6, so you can migrate one test at a time. We recommend you try out and move to the newer Should-* assertions.
The Should-* assertions​
Pester v6 comes with a new set of Should-* assertions that have been built from the ground up.
If you've previously tested the Assert-module, these will be familiar.
Check out Command Reference in the sidebar to read more about the new assertions, e.g. Should-BeString.
These new assertions are split into these categories based on their usage:
- Value
- Collection
- Generic
- Combinator
Each of these categories treats $Actual and $Expected values differently, to provide a consistent behavior when using the | syntax.
Value vs. Collection assertions​
The $Actual value can be provided by two syntaxes, either by pipeline (|) or by parameter (-Actual):
1 | Should-Be -Expected 1
Should-Be -Actual 1 -Expected 1
Using pipeline syntax​
When using the pipeline syntax, PowerShell unwraps the input and we lose the type of the collection on the left side. We are provided with a collection that can be either $null, empty or have items. Notably, we cannot distinguish between a single value being provided, and an array of single item:
1 | Should-Be
@(1) | Should-Be
These will both be received by the assertion as @(1).
For this reason a value assertion will handle this as 1, but a collection assertion will handle this input as @(1).
Another special case is @(). A value assertion will handle it as $null, but a collection assertion will handle it as @().
$null remains $null in both cases.
# Should-Be is a value assertion:
1 | Should-Be -Expected 1
@(1) | Should-Be -Expected 1
$null | Should-Be -Expected $null
@() | Should-Be -Expected $null # @() is handled as $null by a value assertion
# This fails, because -Expected does not allow collections.
@() | Should-Be -Expected @()
# Should-BeCollection is a collection assertion:
1 | Should-BeCollection -Expected @(1)
@(1) | Should-BeCollection -Expected @(1)
@() | Should-BeCollection -Expected @()
# This fails, because -Expected requires a collection.
$null | Should-BeCollection -Expected $null
Using the -Actual syntax​
The value provided to -Actual is always exactly the same as provided.
Should-Be -Actual 1 -Expected 1
# This fails, Actual is collection, while expected is int.
Should-Be -Actual @(1) -Expected 1
The pipeline is convenient, but it reshapes your input. When the exact shape matters — a single-item collection, an empty collection, $null, or a dictionary — prefer -Actual, which preserves the value exactly. See Input-shape hints for the failures this causes and the hints Pester prints to help.
Value assertions​
Generic value assertions​
Generic value assertions, such as Should-Be, are for asserting on a single value. They behave quite similar to PowerShell operators, e.g. Should-Be maps to -eq.
The $Expected accepts any input that is not a collection.
The type of $Expected determines the type to be used for the comparison.
$Actual is automatically converted to that type.
1 | Should-Be -Expected $true
Get-Process -Name Idle | Should-Be -Expected "System.Diagnostics.Process (Idle)"
The assertions in the above examples will both pass:
1converts tobool-value as$true, which is the expected value.Get-Processretrieves theIdleprocess (on Windows). This process object gets converted tostringwhich is equal to the expected value.
When an assertion fails it throws, and the message shows the expected and the actual value:
2 | Should-Be 1
Expected [int] 1, but got [int] 2.
Use -Because to append the reason the test should pass; it is woven into the message:
2 | Should-Be 1 -Because 'the config default must be 1'
Expected [int] 1, because the config default must be 1, but got [int] 2.
Type specific value assertions​
Type specific assertions are for asserting on a single value of a given type like boolean.
These assertions take the advantage of being more specialized to provide a type specific functionality, such as Should-BeString -IgnoreWhitespace.
$Expectedaccepts input that has the same type as the assertion type. E.g.Should-BeString -Expected "my string".$Actualaccepts input that has the same type as the assertion type. The input is not converted to the destination type unless the assertion specifies it, e.g.Should-BeFalsywill convert tobool.
For example, Should-BeTrue asserts on a boolean:
$true | Should-BeTrue # passes
$false | Should-BeTrue # fails
Expected [bool] $true, but got: [bool] $false.
Should-BeString compares strings and points at the first character that differs:
'Jakub' | Should-BeString 'Tomas'
Expected strings to be the same, but they were different.
String lengths are both 5.
Strings differ at index 0.
Expected: 'Tomas'
But was: 'Jakub'
^
Should-HaveType asserts on the type of a value:
'hello' | Should-HaveType ([string]) # passes
1 | Should-HaveType ([string]) # fails
Expected value to have type [string], but got [int] 1.
Should-BeGreaterThan is a comparison assertion and reports the actual value that failed the comparison:
10 | Should-BeGreaterThan 5 # passes
1 | Should-BeGreaterThan 5 # fails
Expected the actual value to be greater than [int] 5, but it was not. Actual: [int] 1
Collection assertions​
Collection assertions operate on the whole collection provided to $Actual instead of unwrapping it to a single value. Use them whenever you want to assert on multiple items at once.
Generic collection assertions​
Should-BeCollection compares two collections by first comparing their size, and then comparing each item. The $Expected value must be a collection.
1, 2, 3 | Should-BeCollection @(1, 2, 3)
@(1) | Should-BeCollection @(1)
# This fails, one item differs.
1, 2, 3 | Should-BeCollection @(1, 2, 4)
Expected [Object[]] @(1, 2, 4) to be present in [Object[]] @(1, 2, 3) in any order, but some values were not.
Missing in actual: '4 (index 2)'
Extra in actual: '3 (index 2)'
You can also assert on the size of a collection without comparing items, by using -Count:
1, 2, 3 | Should-BeCollection -Count 3
Should-ContainCollection and Should-NotContainCollection check whether the expected items are (or are not) present in the provided collection, in order.
1, 2, 3 | Should-ContainCollection @(1, 2)
1, 2, 3 | Should-NotContainCollection @(3, 4)
Combinator assertions​
Combinator assertions take a -FilterScript and run it against every item in the collection. The filter can be a plain PowerShell expression or another Should-* assertion.
Should-All passes when every item matches the filter:
1, 2, 3 | Should-All { $_ -gt 0 } # passes
1, 2, 3 | Should-All { $_ | Should-BeGreaterThan 0 }
1, 2, 3 | Should-All { $_ -gt 1 } # fails
Expected all items in collection @(1, 2, 3) to pass filter { $_ -gt 1 }, but 1 of them 1 did not pass the filter.
Should-Any passes when at least one item matches the filter:
1, 2, 3 | Should-Any { $_ -gt 2 } # passes
1, 2, 3 | Should-Any { $_ | Should-BeGreaterThan 2 }
1, 2, 3 | Should-Any { $_ -gt 5 } # fails
Expected at least one item in collection @(1, 2, 3) to pass filter { $_ -gt 5 }, but none of the items passed the filter.
Deep object comparison​
To compare whole objects, hashtables, or nested structures by value — instead of a single scalar or a flat collection — use Should-BeEquivalent. It walks properties and nested objects recursively and is order-insensitive for collections.
@{ Name = 'Jakub'; Age = 31 } | Should-BeEquivalent @{ Name = 'Tomas'; Age = 31 }
Expected and actual are not equivalent!
Expected:
@{Age=31; Name='Tomas'}
Actual:
@{Age=31; Name='Jakub'}
Summary:
Expected hashtable @{Age=31; Name='Tomas'}, but got @{Age=31; Name='Jakub'}.
Expected property .Name with value 'Tomas' to be equivalent to the actual value, but got 'Jakub'.
See the dedicated Should-BeEquivalent page for a deep dive: PSCustomObjects, nested objects, collections, and the -ExcludePath, -ExcludePathsNotOnExpected, and -Comparator options.
Input-shape hints​
The Should-* assertions accept their input through the pipeline (| Should-…) or the -Actual parameter. The pipeline is convenient, but PowerShell reshapes whatever is on the left side before the assertion ever sees it:
- a one-item collection is unwrapped to its single element,
- a multi-item collection is streamed and re-collected as a fresh
[object[]](its original type is lost), - a dictionary/hashtable is passed through as one object and is never enumerated,
$nullstays$nulland an empty collection@()sends nothing at all.
Passing the value with -Actual instead preserves it exactly.
When an assertion fails and Pester detects that the input was very likely the wrong shape, it appends an extra line that starts with Hint: to the failure message. The hint never changes whether an assertion passes or fails — it only appears on a failure, to explain the gotcha and how to fix it.
Hints are best-effort diagnostics shown only on failure. A passing assertion never prints a hint, and an ordinary mismatch (for example a plain scalar that simply is not equal) does not print one either.
Collection assertions — scalar, $null, or a dictionary​
Should-BeCollection compares the whole input as one collection. Piping a lone scalar, $null, or a dictionary is almost never what you meant, so all three get a hint.
A scalar:
5 | Should-BeCollection @(1)
Expected [Object[]] @(1) to be present in [Object[]] @(5) in any order, but some values were not.
Missing in actual: '1 (index 0)'
Extra in actual: '5 (index 0)'
Hint: You piped a single [int] into a collection assertion. It is treated as a single item. To assert on a one-item collection wrap it as ,$actual, or use Should-Be for a scalar value.
$null (treated as a single $null item, not an empty collection):
$null | Should-BeCollection @(1)
Expected [Object[]] @(1) to be present in [Object[]] @($null) in any order, but some values were not.
Missing in actual: '1 (index 0)'
Extra in actual: '$null (index 0)'
Hint: You piped $null into a collection assertion. It is treated as a single $null item, not an empty collection. Use @() to represent an empty collection.
A dictionary/hashtable (passed through as one object):
@{ Name = 'Jakub'; Age = 31 } | Should-BeCollection @(1)
Expected [Object[]] @(1) to be present in [Object[]] @(@{Age=31; Name='Jakub'}) in any order, but some values were not.
Missing in actual: '1 (index 0)'
Extra in actual: '@{Age=31; Name='Jakub'} (index 0)'
Hint: You piped a single [hashtable] into a collection assertion. PowerShell treats a dictionary as a single object, not a collection. To assert on it as a hashtable use Should-BeHashtable, or compare its contents with Should-BeEquivalent.
The same wrong shapes get a hint through -Actual too, with slightly different wording because nothing was piped:
Should-BeCollection -Actual @{ Name = 'Jakub'; Age = 31 } -Expected @(1)
Actual [hashtable] @{Age=31; Name='Jakub'} is not a collection.
Hint: -Actual is a single [hashtable], which is not a collection. PowerShell treats a dictionary as a single object, not a collection. To assert on it as a hashtable use Should-BeHashtable, or compare its contents with Should-BeEquivalent.
Item-wise collection assertions — a dictionary​
Should-All, Should-Any, Should-ContainCollection and Should-NotContainCollection iterate or search the input item by item. A lone scalar or $null is a perfectly valid one-item collection here, so they are not flagged. A dictionary is the genuine gotcha — PowerShell passes it through as a single object instead of enumerating it:
@{ Name = 'Jakub'; Age = 31 } | Should-All { $_ -gt 0 }
Expected all items in collection @(@{Age=31; Name='Jakub'}) to pass filter { $_ -gt 0 }, but 1 of them @{Age=31; Name='Jakub'} did not pass the filter.
Reasons :
Cannot compare "System.Collections.Hashtable" because it is not IComparable.
Hint: You piped a single [hashtable] into a collection assertion. PowerShell treats a dictionary as a single object, so it is passed through as one item instead of being iterated. Enumerate it first, e.g. with $actual.GetEnumerator(), or its .Keys or .Values, or assert on it directly with Should-BeHashtable.
Type assertions — a piped collection​
Should-HaveType and Should-NotHaveType check a single value against a type. Piping a collection unwraps it, so the type you meant to check is lost before the assertion runs. A single-item collection collapses to its one element:
[string[]]('a') | Should-HaveType ([string[]])
Expected value to have type [string[]], but got [string] 'a'.
Hint: You piped a [string[]] into a type assertion, but the pipeline unwraps a single-item collection to its one element, so the assertion saw a single [string], not the [string[]] you piped. To assert the type of a collection, pass it as the -Actual argument instead of piping it, e.g. -Actual $value.
A multi-item collection is streamed and re-collected as [object[]]:
[string[]]('a', 'b') | Should-HaveType ([string[]])
Expected value to have type [string[]], but got [Object[]] @('a', 'b').
Hint: You piped a [string[]] into a type assertion, but the pipeline streams a multi-item collection and re-collects it as [Object[]], so the assertion saw [Object[]], not the [string[]] you piped. To assert the type of a collection, pass it as the -Actual argument instead of piping it, e.g. -Actual $value.
As the hint says, pass the collection with -Actual to keep its real type — Should-HaveType -Actual ([string[]]('a', 'b')) -Expected ([string[]]) passes.
Single-value assertions — a piped collection​
Should-Be and the other single-value assertions (the comparison, boolean, string, $null, and time assertions) inspect one value. Piping a collection collapses it into a single value, so the assertion silently compares the collapsed value instead of the collection:
1, 2, 3 | Should-Be 1
Expected [int] 1, but got [Object[]] @(1, 2, 3).
Hint: You piped a [Object[]] into a single-value assertion, but the pipeline streams a multi-item collection and re-collects it into a single [Object[]], so the whole collection was inspected as one value. To assert on a collection use Should-BeCollection or Should-BeEquivalent; to assert on a single value pass it as the -Actual argument instead of piping it, e.g. -Actual $value.
Pipeline vs. -Actual​
The hints all point at the same root cause: the pipeline reshapes your input, -Actual does not.
- Pipe a value when you want the convenient, unwrapped behavior and the shape does not matter.
- Use
-Actual(or the assertion the hint suggests —Should-BeCollection,Should-BeEquivalent,Should-BeHashtable) when the exact shape matters: a collection whose type you care about, a one-item collection, an empty collection,$null, or a dictionary.
Assertion reference​
All Should-* assertions are listed below, grouped by the kind of check they perform. Follow a link to see the full syntax, parameters, and examples in the Command Reference.
General​
Should-Be— Compares the expected value to the actual value to see if they are equal.Should-NotBe— Compares the expected value to the actual value to see if they are not equal.Should-BeGreaterThan— Asserts that the actual value is greater than the expected value.Should-BeGreaterThanOrEqual— Asserts that the actual value is greater than or equal to the expected value.Should-BeLessThan— Asserts that the actual value is less than the expected value.Should-BeLessThanOrEqual— Asserts that the actual value is less than or equal to the expected value.Should-BeNull— Asserts that the input is$null.Should-NotBeNull— Asserts that the input is not$null.Should-BeSame— Asserts that the actual value is the same instance as the expected value.Should-NotBeSame— Asserts that the actual value is not the same instance as the expected value.Should-HaveType— Asserts that the input is of the expected type.Should-NotHaveType— Asserts that the input is not of the expected type.
Boolean​
Should-BeTrue— Asserts that the actual value is$true.Should-BeFalse— Asserts that the actual value is$false.Should-BeTruthy— Asserts that the actual value is truthy.Should-BeFalsy— Asserts that the actual value is falsy (0,"",$nullor@()).
String​
Should-BeString— Asserts that the actual value is equal to the expected string. Supports-CaseSensitive,-IgnoreWhitespaceand-TrimWhitespace.Should-NotBeString— Asserts that the actual value is not equal to the expected string.Should-BeEmptyString— Asserts that the input is an empty string.Should-NotBeEmptyString— Asserts that the input is a string that is not$nullor empty.Should-NotBeWhiteSpaceString— Asserts that the input is a string that is not$null, empty, or whitespace only.Should-BeLikeString— Asserts that the actual value matches the expected wildcard pattern.Should-NotBeLikeString— Asserts that the actual value does not match the expected wildcard pattern.Should-MatchString— Asserts that the actual value matches the expected regular expression.Should-NotMatchString— Asserts that the actual value does not match the expected regular expression.
Collection​
Should-BeCollection— Compares collections for equality, by comparing their size and each item.Should-ContainCollection— Asserts that the expected items are present in the provided collection, in order.Should-NotContainCollection— Asserts that the expected items are not present in the provided collection.Should-All— Asserts that every item in the collection matches a filter.Should-Any— Asserts that at least one item in the collection matches a filter.
Hashtable​
Should-BeHashtable— Compares a dictionary/hashtable against expected keys and values.
Equivalency​
Should-BeEquivalent— Recursively compares two objects for equivalency, by comparing their properties. See the dedicated Should-BeEquivalent page for a walkthrough with rendered output.
DateTime and TimeSpan​
Should-BeBefore— Asserts that the actual[datetime]is before the expected[datetime].Should-BeAfter— Asserts that the actual[datetime]is after the expected[datetime].Should-BeFasterThan— Asserts that the provided[timespan]or[scriptblock]is faster than the expected[timespan].Should-BeSlowerThan— Asserts that the provided[timespan]or[scriptblock]is slower than the expected[timespan].
Exception​
Should-Throw— Asserts that a script block throws an exception.
Mock​
Should-Invoke— Asserts that a mocked command was called the expected number of times. See Mocking.Should-NotInvoke— Asserts that a mocked command was not called. See Mocking.
Command parameters​
Should-HaveParameter— Asserts that a command has the expected parameter, and optionally checks its type, default value, aliases, parameter set, mandatory status, and argument completer.Should-NotHaveParameter— Asserts that a command does not have the given parameter.
Choosing your assertion syntax​
The classic Should -Be assertions still ship and still work, and the new Should-* assertions sit alongside them. You can adopt them one test at a time, or mix both styles in the same suite while you migrate.
When you are ready to commit to the new style, switch the old syntax off so it can't be used by accident:
$config = New-PesterConfiguration
$config.Should.DisableV5 = $true
With Should.DisableV5 enabled, using the classic Should -Be syntax throws, pointing you at the new command:
Pester Should -Be syntax is disabled. Use Should-Be (without space), or enable it by setting: $PesterPreference.Should.DisableV5 = $false
Should (v5)​
Should is the classic assertion syntax from Pester v5. It is still fully supported in v6 and uses parameter sets like Should -Be, Should -Match, or Should -Throw:
"Pester is bad." | Should -Be "Pester is awesome!"
Which throws an exception with this text to fail the test:
Expected strings to be the same, but they were different.
Expected length: 18
Actual length: 14
Strings differ at index 10.
Expected: 'Pester is awesome!'
But was: 'Pester is bad.'
----------^
This is the older style. The full list of operators (-Be, -BeExactly, -BeGreaterThan, -Match, -Throw, -HaveParameter, and the rest) lives on the dedicated Classic assertions (v5) page. For new tests, prefer the Should-* assertions above.
Collect all Should failures​
Should can be configured to continue on failure instead of stopping the test at the first error. Every failure is collected and reported together at the end of the test, so you can put multiple assertions into one It and still get complete information on failure. This is called a soft assertion, and it works for both the classic Should -Be syntax and the new Should-* assertions.
Enable it globally by setting Should.ErrorAction = 'Continue' on the configuration object (or via $PesterPreference), and override it on a single assertion with -ErrorAction Stop / -ErrorAction Continue.
See Soft assertions for the full explanation, examples, and how to guard preconditions.