Miista / pose

Replace any .NET method (including static and non-virtual) with a delegate
MIT License
22 stars 3 forks source link

Cannot shim generic method on abstract base class #46

Open Miista opened 4 months ago

Miista commented 4 months ago

MVE:

// Classes
abstract class AbstractBase
{
    public virtual T GetTFromAbstractBase<T>(string input) where T : class => null;
}

class DerivedFromAbstractBase : AbstractBase {}

// Test
var shim = Shim
    .Replace(() => Is.A<AbstractBase>().GetTFromAbstractBase<string>(Is.A<string>()))
    .With((AbstractBase @this, string @string) => "Hello");

PoseContext.Isolate(() =>
  {
      var instance = new DerivedFromAbstractBase();
      var result = instance.GetTFromAbstractBase<string>("");
  },
  shim
);

Rewriting GetTFromAbstractBase results in System.BadImageFormatException: An attempt was made to load a program with an incorrect format. (0x8007000B).

This issue was discovered during Miista/pose#34

mamen commented 3 months ago

I get the same exception when a method is called on a mocked dependency:

class Foo {

    public Foo(ISomeDependency dep) {
        _dep = dep;
    }

    public void DoSomething() {
        _dep.DoSomething<string>("foo");
    }
}

class FooTests {

    void TestForDoSomething() {
        var fixture = new Foo(MockedDependency); 

        PoseContext.Isolate(() =>
        {
            actual = fixture.DoSomething();
        }, shim);
    }
}

Is this the same problem, because I am also using a generic method (DoSomething<string>()) inside an instance method or should I open a new issue?

Miista commented 3 months ago

@mamen It might be. It could be related to how the constrained instruction is handled in the rewrite process (see #49). I believe that the current implementation is incorrect in that it never executes the replacement method.