Mocking a private generic property on a generic class throws TypeMockException

+1 vote

I'm trying to mock a generic class such that the constructor only assigns one of the generic properties, as follows:

using System;

using TypeMock;
using TypeMock.ArrangeActAssert;

namespace RD.MobileClient.Core.BDDTests
{
    class GenericClass<T>
    {
        public T Foo { get; private set; }

        public Object Bar { get; private set; }

        public GenericClass(T foo, Object bar)
        {
            this.Foo = foo;
            this.Bar = bar;
        }
    }
    class Test
    {
        public Test()
        { 
            // Also tried with Members.CallOriginal and Members.MustBeSpecified. Same problem.
            GenericClass<string> fake_generic_class = Isolate.Fake.AllInstances<GenericClass<string>>(Members.ReturnRecursiveFakes, ConstructorWillBe.Ignored);
            
            MockManager.GetMockOf(fake_generic_class).MethodSettings(".ctor").MockMethodCalled += (sender, args) =>
            {
                GenericClass<string> inst = (GenericClass<string>) sender;

                // Exception throws by the following line
                ObjectState.SetField(inst, "Foo", (string) args.SentArguments[0]);
            };

            GenericClass<string> test = new GenericClass<string>("testing", null);
        }
    }
}

But I get a exception saying "Field 'Foo' could not be found in type: GenericClass`1, did you mean to mock the property? As a property is a method, use mocking API instead".

asked Sep 4 by Ash (180 points)

1 Answer

0 votes

Hey Ash,

Try to use:

GenericClass<string> fake_generic_class = Isolate.Fake.Instance<GenericClass<string>(Members.ReturnRecursiveFakes, ConstructorWillBe.Ignored);
 
Instead of:
 
GenericClass<string> fake_generic_class = Isolate.Fake.AllInstances<GenericClass<string>>(Members.ReturnRecursiveFakes, ConstructorWillBe.Ignored);
 
Let me know if that helps!
Cheers, Sapir.
 
 
answered Sep 4 by SapirTypemock (1,130 points)
Thanks Sapir.

That may work, yes, but since I'm dealing with legacy code, I need all future instances that are created to be fakes. The classes I'm testing really do not lend well to dependency injection unfortunately, and they do nasty things like create instances all over the place internally.
This is why I do 'AllInstances', so that I'm in control as much as possible.

Hope that makes sense.

Thanks for your help,
Ash

Hi Ash,

You're using the old API. In this case, you can use the ctor custom logic:

public void Test1()
        {
            GenericClass<string> fake_generic_class = Isolate.Fake.NextInstance<GenericClass<string>>(Members.ReturnRecursiveFakes,
                context => {
                    Isolate.NonPublic.Property.WhenGetCalled(context.Instance,"Foo").WillReturn(context.Parameters[0]);
                });

            GenericClass<string> test = new GenericClass<string>("testing", null);
            
            Assert.AreEqual("testing", test.Foo);
        }

Using 'AllInstances' creates a handle (e.g. fake_generic_class in our example). With the handle, you control the behavior of all instances. (When you set method behavior you'll set it on the handle and not on every instance).

...