The Real Dependency and the Real Execution Identity

PesterForge · July 2026 · 8 min read

📦 Run it yourself — the companion repository reserves companion/tests/Integration/ for tests that use real adapters and controlled test resources.

The phrase “works on my machine” is usually treated as a joke.

For PowerShell automation, it is also a precise diagnosis.

Your machine may have:

Production may have none of them.

A unit test with mocks cannot prove that the real dependency and the real execution identity can complete the work.

What you will learn

What a mock actually proved

In the fast gate, we might use:

Mock Get-PfgOperationState { 'NotStarted' }

That proves how our code behaves when the state adapter returns NotStarted.

It does not prove:

Those are integration claims.

The production identity is a dependency

Teams often write “test against the real API” and forget the account that will call it.

The same endpoint may behave differently for:

The identity controls more than authorization. It also changes the environment PowerShell sees.

The SFTP intake example

The Partner Feed Guardian receives partner files through SFTP. The developer tests successfully from a console:

Get-SftpPartnerBatch -PartnerId NORTHWIND

The scheduled job fails.

Possible causes include:

None of these are bugs in the eligibility function. They are production integration failures.

Create an environment fingerprint

Before testing the remote operation, capture the environment that matters:

function Get-PfgExecutionFingerprint {
    [CmdletBinding()]
    param()

    [pscustomobject]@{
        UserName          = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
        PowerShellVersion = $PSVersionTable.PSVersion.ToString()
        Edition           = $PSVersionTable.PSEdition
        ProcessBitness    = if ([Environment]::Is64BitProcess) { '64-bit' } else { '32-bit' }
        CurrentDirectory  = (Get-Location).Path
        ModulePath        = $env:PSModulePath -split [IO.Path]::PathSeparator
        NonInteractive    = -not [Environment]::UserInteractive
    }
}

On non-Windows systems, use a cross-platform identity method instead of WindowsIdentity. The point is not the exact implementation. The point is to record the environment under which the evidence was produced.

A test can assert the approved identity and PowerShell version:

It 'runs under the approved intake identity' {
    $fingerprint = Get-PfgExecutionFingerprint

    $fingerprint.UserName | Should-BeString 'CONTOSO\svc-partner-intake'
    $fingerprint.PowerShellVersion |
        Should-MatchString '^7\.(4|5|6)\.'
}

Be cautious with overly exact environment checks. Pin what the operation requires, not every incidental detail.

Test the real module path

A common production failure is loading the wrong module version.

It 'loads the approved SFTP adapter version' {
    $module = Get-Module -ListAvailable PartnerSftpAdapter |
        Sort-Object Version -Descending |
        Select-Object -First 1

    $module | Should-NotBeNull
    $module.Version.ToString() | Should-BeString '3.2.1'
}

This is not a generic “package exists” infrastructure example. The test is tied to a specific compatibility requirement for the production intake adapter.

Better still, run a real adapter operation and record the loaded module version in the test result or execution evidence.

Test access without processing a real batch

Integration tests should use a dedicated test partner or isolated folder.

Describe 'Partner SFTP integration' -Tag 'Layer.Integration', 'Environment.Lab' {
    BeforeAll {
        $partnerId = 'PFG-INTEGRATION'
        $testBatchId = 'INTEGRATION-{0}' -f ([guid]::NewGuid().Guid)
    }

    It 'authenticates and lists the isolated integration folder' {
        $items = Get-SftpPartnerItem -PartnerId $partnerId -Path '/integration'

        $items | Should-NotBeNull
    }
}

A good test resource is:

Do not point the integration test at the normal inbound directory and hope naming conventions are enough.

Test the provider’s real error shape

Your unit test may simulate:

throw 'Access denied'

The real adapter may throw a nested exception, write a nonterminating error, return a status object, or emit a native exit code.

An integration test should establish the behavior your production wrapper actually sees.

It 'returns an actionable authentication failure for an invalid integration key' {
    {
        Get-SftpPartnerItem `
            -PartnerId 'PFG-INTEGRATION-INVALID' `
            -Path '/integration' `
            -ErrorAction Stop
    } | Should-Throw -ExceptionType ([System.UnauthorizedAccessException])
}

Use a deliberately invalid test identity or endpoint designed for this purpose. Do not repeatedly lock a real service account to test failure handling.

Run the same command noninteractively

A manual console is not the production host.

Run the integration suite through the actual mechanism whenever possible:

For a scheduled task, create a test task using the same account and PowerShell executable but a controlled command:

pwsh.exe -NoLogo -NoProfile -NonInteractive `
    -File C:\PfgTests\Invoke-IntegrationGate.ps1

-NoProfile is especially valuable. If the production automation requires profile initialization, make that dependency explicit rather than letting it arrive accidentally from a developer profile.

Separate dependency unavailability from assertion failure

When a test cannot reach its lab dependency, the result needs a clear classification.

Do not turn this:

SFTP lab unavailable

into this:

Partner eligibility logic failed

They require different owners and different responses.

A setup block can stop the integration container with an actionable error:

BeforeAll {
    if (-not (Test-PfgIntegrationEnvironment)) {
        throw 'PFG integration environment is unavailable. Owner: Partner Platform.'
    }
}

For a required release gate, an unavailable dependency should stop the gate. Silently skipping the suite and calling the release green is not acceptable.

For an optional developer run, you may provide a separate configuration that excludes integration tests entirely.

Keep integration tests narrow

A real dependency does not justify testing everything through it.

Use integration tests to prove the boundary:

Continue testing the full decision table in the fast gate. It is faster and easier to diagnose there.

Make test data disposable, not mysterious

Every created integration object should have:

Example batch ID:

$batchId = 'PFG-INT-{0:yyyyMMddHHmmss}-{1}' -f `
    (Get-Date).ToUniversalTime(), `
    ([guid]::NewGuid().Guid.Substring(0, 8))

This makes abandoned resources discoverable after a failed teardown.

Teardown is helpful, not infallible

Use AfterAll to clean controlled resources:

AfterAll {
    Remove-PfgIntegrationBatch -BatchId $batchId -ErrorAction Continue
}

But also provide an independent cleanup command:

Remove-PfgExpiredTestBatch -Prefix 'PFG-INT-' -OlderThan (New-TimeSpan -Hours 4)

The PowerShell host can crash before AfterAll runs. Test safety cannot depend on graceful completion.

Integration test policy

A practical integration profile should document:

Field Example
Environment Dedicated PFG integration endpoint
Identity svc-pfg-integration
State changes Isolated test folder only
Frequency Before release and nightly
Timeout Five minutes
Failure action Block release; route environment failures to platform owner
Cleanup AfterAll plus scheduled stale-resource cleanup

What these tests prove

They can prove that the actual execution identity, installed adapter, network path, authentication method, and controlled provider resource work together as expected.

What they do not prove

They do not prove that:

Those claims require deployment and production validation.

Try it yourself

Choose one external dependency and answer:

  1. Which identity uses it in production?
  2. Which PowerShell executable and version run the command?
  3. Which module path is visible?
  4. Where are credentials or keys read?
  5. What isolated test resource can be used?
  6. What real failure shape does the provider produce?
  7. How are abandoned test resources found and removed?

Then create one integration test that runs under the production-like identity rather than your own console.

Common mistakes

Running integration tests only as the developer. The production identity is part of the dependency chain.

Using normal inbound folders as test space. Create isolated test resources and business-processing exclusions.

Skipping a required suite when the lab is unavailable. Unavailable evidence is not passing evidence.

Testing the full decision matrix through a slow provider. Keep logic in the fast gate; prove the boundary here.

Relying entirely on AfterAll cleanup. Provide independent discovery and removal of stale test state.

Recap

Mocks prove your code’s behavior against controlled scenarios. Integration tests prove that the real dependency and real execution identity can work together.

For production PowerShell, identity, module path, noninteractive behavior, credentials, and provider error shape are not background details. They are testable dependencies.

Next up: Part 5 — State Changes, Partial Failure, and Safe Repetition. We will test what happens when publication succeeds, acknowledgement fails, and the automation must run again without duplicating production data.


← All posts