Skip to content
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

MethodArgumentConversionInvalidCastArgument: Cannot convert the "HeaderInterceptor" value of type "HeaderInterceptor" to type "HeaderInterceptor" #2241

Closed
3 tasks done
maccluu opened this issue Aug 16, 2022 · 7 comments

Comments

@maccluu
Copy link

maccluu commented Aug 16, 2022

Checklist

What is the issue?

Thanks for taking the time to read my question!

I'm having an issue \w Pester. When several tests are run with one Invoke-Pester cmd, I suddenly get PSInvalidCastException on blocks where I'm passing an inherited test class to a method that takes its parent, below is the problematic code taken from the test and production code:

class TestInterceptor : HeaderInterceptor
{
    [void] Intercept([ApiRequest]$Request)
    {
       .... # override \w test data
    }
}

[void] AddClientHeaderInterceptor([HeaderInterceptor]$HeaderInterceptor)
{
  ....
}

It 'Adds new host interceptor to all clients' {

   $interceptor = [TestInterceptor]::new()

FAILS>> $testService.AddClientHeaderInterceptor($interceptor)
}

ERROR:
Cannot convert argument "HeaderInterceptor", with value: "HeaderInterceptor", for "AddClientHeaderInterceptor" to type "HeaderInterceptor": "Cannot convert the "HeaderInterceptor" value of type "HeaderInterceptor" to type "HeaderInterceptor"

The tests pass when run on their own (Invoke-Pester $testFile) in the same PWSH session, but when run with Invoke-Pester -configuration $config (Default config) and ran against all test files it fails. I've thus far been unable to replicate by running each test manually, in that case everything passes.

The only change is that I've added a using module to a module that is widely imported.

Expected Behavior

I can take that same test class and manually cast it in a separate pwsh session.

using module ApiClientCore
class TestInterceptor : HeaderInterceptor
>> {
>>     [void] Intercept([ApiRequest]$Request)
>>     {
>>         $Request.Headers['Foo'] = 'Bar'
>>     }
>> }
>$t = [TestInterceptor]::new()
>[HeaderInterceptor]$t
TestInterceptor

Steps To Reproduce

Describe your environment

Pester version : 5.3.1 C:\Users\mike\Documents\PowerShell\Modules\Pester\5.3.1\Pester.psm1
PowerShell version : 7.2.6
OS version : Microsoft Windows NT 10.0.19043.0

Possible Solution?

Through debugging, I have a vague sense that it has something to do \w the AppDomain loading in different version of the same object and when attempting to cast between versions I get the error above. That piece is outside of my understanding atm however.

>$t = [TestInterceptor]::New()
>$t.GetType().Assembly.FullName
PowerShell Class Assembly, Version=1.0.0.69, Culture=neutral, PublicKeyToken=null
>[HeaderInterceptor]::new().getType().Assembly.FullName
PowerShell Class Assembly, Version=1.0.0.71, Culture=neutral, PublicKeyToken=null
>[HeaderInterceptor]$t

InvalidArgument: Cannot convert the "TestInterceptor" value of type "TestInterceptor" to type "HeaderInterceptor".
@fflaten
Copy link
Collaborator

fflaten commented Aug 16, 2022

Please update with a minimal and complete sample incl. psm1, ps1 and a testfile with setup and single test.

Currently unable to understand in what files and/or modules which classes exist in, where the classes are instantiated (in Pester file? in BeforeAll/root/It?) etc. Classes in PowerShell are complex, so hard to debug without realistic repro.

@maccluu
Copy link
Author

maccluu commented Aug 16, 2022

Reasonable - it is quite complex as there is several modules. Let me see if I can replicate it outside of our codebase, so I have something to share.

Classes are instantiated in the pester test file typically via inheritance with methods overrided with test data but then passed back to methods in the production code where we see this method argument casting exception.

@fflaten fflaten closed this as not planned Won't fix, can't repro, duplicate, stale Oct 31, 2022
@fflaten
Copy link
Collaborator

fflaten commented Oct 31, 2022

Closing as not reproducible atm.

@maccluu
Copy link
Author

maccluu commented Dec 9, 2022

@fflaten - curious if your final workaround in #1920 is the ideal way to write test classes that need pieces mocked?

Separately, we've also been inheriting, in the test script, all classes from the module regardless of needing to mock anything. I believe this was an attempt to address the issue I'm running into in my original post, idea being there's not two classes floating around during the test, only instantiate the TestClass.

Sorry for not following up, I've been unable to reproduce the error in a smaller module set, from my testing

@fflaten
Copy link
Collaborator

fflaten commented Dec 9, 2022

I rarely use classes myself due to issues like this. So don't really have any recommendations atm.

Contributions to pester/docs on this topic are welcome from people with more experience and battle-scars 😁

@maccluu
Copy link
Author

maccluu commented Dec 9, 2022

Fair! Let me gain some more confidence in PWSH and I'll definitely do that!

But for sure everything should be in a block (BeforeAll, Describe, etc etc)

@fflaten
Copy link
Collaborator

fflaten commented Dec 9, 2022

In general, yes.

I would also try to keep module imports and/or using module ... in a bootstrap-script like test.ps1 and use clean PowerShell-sessions when classes are involved. Might be more consistent as you avoid class version conflict and reimports.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants