chevron-thin-right chevron-thin-left brand cancel-circle search youtube-icon google-plus-icon linkedin-icon facebook-icon twitter-icon toolbox download check linkedin phone twitter-old google-plus facebook profile-male chat calendar profile-male
Welcome to Typemock Community! Here you can ask and receive answers from other community members. If you liked or disliked an answer or thread: react with an up- or downvote.
0 votes
Is there some way to create a fake from a System.Type?

Thanks,
-Kevin
asked by kevinms99 (4.4k points)

6 Answers

0 votes
 
Best answer
Hi Kevin,

You can use this workaround for now:

                
        [TestMethod]
        public void MethodUnderTest_Scenario_ExpectedResult()
        {
            Provider provider = new Provider();
            Isolate.WhenCalled(() => provider.GetService(null)).DoInstead(callContext =>
                {
                    var requestedType = (Type) callContext.Parameters[0];
                    var faker = Isolate.Fake.GetType();
                    var instanceMethod = faker.GetMethod("Instance", new Type[0]);
                    var genericMethod = instanceMethod.MakeGenericMethod(requestedType);

                    return genericMethod.Invoke(Isolate.Fake, new object[0]);
                });

            var s = provider.GetService(typeof(SomeUserType));
            Console.WriteLine(s);
        }

    


We will add support for creating dynamically fakes soon.

Please let me know if it helps.
answered by NofarC (4k points)
selected by kevinms99
0 votes
Hi Kevin,

Unfortunately, you can't fake System.Type directly. I'll add it to our backlog to our mscorlib supported type.
The workaround is to wrap the call to System.Type with a method in your class that calls it. Now you can fake the call to that method.

May I ask, in what scenario are you trying to replace a type?
answered by gilz (14.5k points)
0 votes
I'm not looking to create a fake for System.Type. I'm looking to create a fake for the type that the System.Type represents.

I have a method more or less like:

object GetService(System.Type type)
{
return _dictionaryOfTypeToInstance[type];
}

The calling code would then cast the returned object to the type of interest:

void SomeCallingCode()
{
SomeUserType obj = (SomeUserType)provider.GetService(typeof(SomeUserType));
}

I'd like to mock out the call to GetService above. In order to work, the underlying fake needs to support the type passed to the method.

Thanks,
-Kevin
answered by kevinms99 (4.4k points)
0 votes
Gotcha. I think.

So for this class (I simplified it to be in the same class, but it obviously works with other classes too):
    public class Provider
    {
        Dictionary<Type, object> _dictionaryOfTypeToInstance;

        public object GetService(System.Type type)
        {
            // should throw because it's null
            return _dictionaryOfTypeToInstance[type];
        }

        public void SomeCallingCode()
        {
            SomeUserType obj = (SomeUserType)GetService(typeof(SomeUserType));
        }

    }


You have these options three:

1. If you don't care about the type at all, and plan to work according to sequence, you can use this:
[TestMethod]
public void Regardless_Of_Arguments_Just_Based_On_Call_Sequence()
{
    Provider provider = new Provider();

    Isolate.WhenCalled(() => provider.GetService(null)).WillReturn(new SomeUserType());
    provider.SomeCallingCode();
}


(note in all options, the fact that the test passes means that the faking succeeded).

2. If you want to be specific about the type in the argument, use this:
[TestMethod]
public void By_Exact_Argument()
{
    Provider provider = new Provider();

    Isolate.WhenCalled(() => provider.GetService(typeof(SomeUserType)))
        .WithExactArguments().WillReturn(new SomeUserType());
    provider.SomeCallingCode();

}


3. If you want to dynamically control this, you can use:
[TestMethod]
public void Dynamically_Control_Return_Value()
{
    Provider provider = new Provider();

    Isolate.WhenCalled(() => provider.GetService(null)).DoInstead(callContext =>
    {
        if (callContext.Parameters[0].GetType() == typeof(SomeUserType))
        {
            return new SomeUserType();
        }
        return null;
    });

    provider.SomeCallingCode();

}


Also for 3, in version 7.3, there's the ability to continue with the original method implementation, so that may be useful too:
callContext.WillCallOriginal();


Does any of these seem to resolve it?
answered by gilz (14.5k points)
0 votes
I think we're getting closer.

The code under test makes a number of calls to GetService with different types. I'd prefer that my unit test doesn't really care what is asked for, and can return a fake for whatever is asked for without me having to modify the unit test code each time the set of types that GetService needs to support is changed in the code under test.

Essentially, I was hoping for something like:

Isolate.WhenCalled(() => provider.GetService(null)).DoInstead(callContext =>
    Type requestedType = (Type)callContext.Parameters[0];
    return Isolate.Fake.Instance(requestedType);


Isolate.Fake.Instance(Type) would return a fake that supports the specified type.

Thanks,
-Kevin
answered by kevinms99 (4.4k points)
0 votes
Sorry it took me so long to reply back to this thread. I was occupied with other things.

Your workaround provides exactly what I was looking for.

Thanks!
answered by kevinms99 (4.4k points)
...