Wednesday 17 August 2022

MSTest PrivateType.InvokeStatic() Throws MissingMethodException

 Problems:

I have this simple class to be tested:

public class Organizer {
    private static bool Bongo(String p) {
        return p != null && p.Length >= 5;
    }

    private static int ValidateArgs(String[] args) {
        return args.Length;
    }
}

and I have this code using MSTest to test the static methods:

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;

public class OrganizerTest {
    [TestMethod]
    public void TestBongo() {
        PrivateType psOrganizers = new PrivateType(typeof(Organizer));

        // This one works fine.
        Assert.IsTrue(Convert.ToBoolean(psOrganizers.InvokeStatic("Bongo", "ABCDEFG")));

        // Fails with: "System.MissingMethodException: Method 'Organizer.Bongo' not Found.
        Assert.IsFalse(Convert.ToBoolean(psOrganizers.InvokeStatic("Bongo", null)));
    }

    [TestMethod]
    public void TestBodo() {
        PrivateType psOrganizers = new PrivateType(typeof(Organizer));

        String[] fakeArray = new String[] { "Pizza" };

        // Fails with: "System.MissingMethodException: Method 'Organizer.ValidateArgs' not Found.
        int result1 = Convert.ToInt32(psOrganizers.InvokeStatic("ValidateArgs", fakeArray));

        // Fails with: "System.MissingMethodException: Method 'Organizer.ValidateArgs' not Found.
        int result2 = Convert.ToInt32(psOrganizers.InvokeStatic("ValidateArgs", "A", "B", "C", "D"));

        // Fails with: "System.MissingMethodException: Method 'Organizer.ValidateArgs' not Found.
        int result3 = Convert.ToInt32(psOrganizers.InvokeStatic("ValidateArgs", new Object[] { "A", "B", "C", "D" }));

        Assert.IsTrue(result1 == 1 && result2 == 4 && result3 == 4);
    }
}

Aside from the first Assert in TestBongo, every other Assert fails due to a MissingMethodException. The are numerous InvokeStatic() overloads and I suspect that it may be the case that the compiler is not selecting the one I expect.

Btw, please do not tell me not to test private methods. I'm not looking for a debate.


Solution:

The last parameter to InvokeStatic is a params parameter so its usage is a little confusing for these cases. In the first case, passing null appears to be treated as an attempt to call a method with no arguments. Try

psOrganizers.InvokeStatic("Bongo", new object[] { null })

to invoke Bongo with null.

In the second case, String[] is implicitly convertible Object[] because of array covariance. The string array is getting passed as the list of arguments rather than the single argument you want. You will need to wrap the string array in another array to get it work correctly. 


Try this below code:


psOrganizers.InvokeStatic("ValidateArgs", new object[] { new string[] { "A", "B", "C", "D" } })

to invoke ValidateArgs.


No comments:

Post a Comment