Answered PrivateObject Invoke throws MissingMethodException

  • Tuesday, May 22, 2012 6:10 PM
     
     

    I'm getting MissingMethodException will I call PrivateObject Invoke:

          var target = new ClassBeingTested();

          var po = new PrivateObject(target);

          po.Invoke("PrivateMethodToTest");

    The exception message is "Method 'xxxxx.PrivateMethodToTest' not found."

    But PrivateMethodToTest is defined in ClassBeingTested:

         private void PrivateMethodToTest(...

    I've tried invoking other methods in ClassBeingTested, and they all fail with the same exception.

    DadCat

      

All Replies

  • Wednesday, May 23, 2012 7:17 PM
     
     

    Hi,

    Can you please provide more details about your installation.  Is it Dev10/Dev10SP1/Dev11 Beta ? 
    Also can you share more specific repro ? Sample steps mentioned above doesn't repro the issue.

    Thanks

  • Friday, May 25, 2012 6:28 AM
    Moderator
     
     

    Thanks for Dhruv’s friendly assistance.

    Hi DadCat,

    Like Dhruv’s suggestion, it will be better if you could provide more detailed information.

    Which VS version are you using?

    If you are using the VS2011 Beta:

    The Private Accessors – This feature was deprecated in the VS2010 product and has been removed in VS11. If you have test projects from VS2010 that include private accessors, they will still work in VS11, but the wizard for creating new ones no longer exists. For detailed information, see What's New in Visual Studio 11 Beta Unit Testing.

    If you are using VS2010, if possible, you could create a simple private class method, and then create a unit test for it, check it, if it works well, so we could make sure that this issue is not related to your VS, and maybe it is related to this specific app. This is the Walkthrough: Creating and Running Unit Tests. It has a sample “Create and Run a Unit Test for a Private Method”. You could check it.

    If we could make sure that it is related to your specific app, since it is hard for us to repro, please attach your Visual Studio project, you can upload it to the sky driver, and then share the download link in your post. We will try to check it.

    If there's any concern, please feel free to let me know.

    Have a nice weekend,


    Jack Zhai [MSFT]
    MSDN Community Support | Feedback to us

  • Friday, May 25, 2012 3:27 PM
     
     

    Here's the details...

    VS2010 10.0.40219.1 SP1Rel   .NET 4.0.30319 SP1Rel

    Here's the method being tested in class XXX. Note there are overloads of this method with different parameter types. Also, the method is static. Could either be the problem ? (although I can't change this)

           private static Equivalence CheckEquivalence(IEnumerable<object> a, IEnumerable<object> b)
            {
                if ((a != null) && (b != null))
                    return Equivalence.Indeterminate;  // both are not-null - need to compare the items

                if ((a == null) && (b == null))
                    return Equivalence.Equivalent;  // both are null - they're equivalent

                // one (but not both) are null

                if ((a == null) && (b.Count() != 0))
                {
                    return Equivalence.NotEquivalent;  // one was null but the other had a non-zero count
                }

                if ((b == null) && (a.Count() != 0))
                {
                    return Equivalence.NotEquivalent;  // one was null but the other had a non-zero count
                }

                return Equivalence.Equivalent; ;   // one was null and the other had a count of zero
            }

    Here's the unit test. PrivateObject.Invoke fails with missing "CheckEquivalence" method exception:

            [TestMethod()]
            [DeploymentItem("xxx.dll")]
            public void XXX_CheckEquivalenceTest()
            {
                var a = new List<Point>();
                a.Add(new Point(1, 2));

                var b = new List<Point>();
                a.Add(new Point(1, 2));

                var target = new XXX();  // not shown

                var po = new PrivateObject(target); 

       fails here =>         var equivalence = po.Invoke("CheckEquivalence", new Type[]{a.GetType() , b.GetType()}, (IEnumerable<object>)a, (IEnumerable<object>)b);
                Assert.AreEqual((XXX.Equivalence)equivalence, XXX.Equivalence.Equivalent);
            }

    Thanks!

    DadCat

  • Monday, May 28, 2012 2:26 AM
    Moderator
     
     

    Hi DadCat,

    Glad to receive your reply.

    I try to repro this issue, but it seems that it is not the whole code of your project, to resolve this issue, would you mind sharing us the whole sample? You could send it to jackzhai at Hotmail dot com. Thanks for your understanding.

    Best Regards,


    Jack Zhai [MSFT]
    MSDN Community Support | Feedback to us

  • Tuesday, May 29, 2012 3:18 PM
     
     

    I can't share the actual code or project... it's extremely confidential.

    But maybe I can reproduce the problem in a simplified project.

    If so, I'll repost and send it to you via email.

    DadCat

  • Tuesday, May 29, 2012 3:50 PM
     
     

    Here's a sanitized and simplified version that fails:

    Private method CheckEquivalence being tested. Unlike the actual production code, CheckEquivalence is not static and is not over-loaded, so that's not the problem.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace Services
    {
        public class Class1
        {
            private Equivalence CheckEquivalence(IEnumerable<object> objectsA, IEnumerable<object> objectsB)
            {
                if ((objectsA != null) && (objectsB != null))
                    return Equivalence.Indeterminate;  // both are not-null - need to do compare the entries

                if ((objectsA == null) && (objectsB == null))
                    return Equivalence.Equivalent;  // both are null - they're equivalent

                // one (but not both) are null

                if ((objectsA == null) && (objectsB.Count() != 0))
                {
                    return Equivalence.NotEquivalent;  // one was null but the other had a non-zero count
                }

                if ((objectsB == null) && (objectsA.Count() != 0))
                {
                    return Equivalence.NotEquivalent;  // one was null but the other had a non-zero count
                }

                return Equivalence.Equivalent; ;   // one was null and the other had a count of zero
            }
        }

        public enum Equivalence { Equivalent, NotEquivalent, Indeterminate };
        
        public class Point
        {
            public Point()
            {
            }
            public Point(double x, double y)
            {
                X = x;
                Y = y;
            }

            public double X { get; set; }
            public double Y { get; set; }
     
        }
    }

    Unit test that fails at PrivateObject.Invoke:

    using System;
    using System.Text;
    using System.Collections.Generic;
    using System.Linq;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using Services;

    namespace TestProject1
    {
        [TestClass]
        public class UnitTest1
        {
            [TestMethod()]
            public void Class1_CheckEquivalenceTest()
            {
                var a = new List<Point>();
                a.Add(new Point(1, 2));

                var b = new List<Point>();
                a.Add(new Point(1, 2));

                var _class1 = new Class1();
                var po = new PrivateObject(_class1);
                var equivalence = po.Invoke("CheckEquivalence", new Type[] { a.GetType(), b.GetType() }, (IEnumerable<object>)a, (IEnumerable<object>)b);
                Assert.AreEqual((Equivalence)equivalence, Equivalence.Equivalent);
            }
        }
    }

    Exception:

    System.MissingMethodException was unhandled by user code
      Message=Method 'Services.Class1.CheckEquivalence' not found.
      Source=mscorlib
      StackTrace:
           at System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams)
           at Microsoft.VisualStudio.TestTools.UnitTesting.PrivateObject.InvokeHelper(String name, BindingFlags bindingFlags, Object[] args, CultureInfo culture)
           at Microsoft.VisualStudio.TestTools.UnitTesting.PrivateObject.Invoke(String name, BindingFlags bindingFlags, Type[] parameterTypes, Object[] args, CultureInfo culture, Type[] typeArguments)
           at Microsoft.VisualStudio.TestTools.UnitTesting.PrivateObject.Invoke(String name, Object[] args)
           at TestProject1.UnitTest1.Class1_CheckEquivalenceTest() in C:\Projects\PrivateObjectInvoke\TestProject1\UnitTest1.cs:line 24
      InnerException:  [none]

    Thanks!

    DadCat

  • Wednesday, May 30, 2012 6:15 AM
    Moderator
     
     

    Hi DadCat,

    Glad to receive your reply.

    It seems that you write your own unit test code. Based on your description, you were testing the Private method CheckEquivalence.

    To narrow down this issue, I add two breakpoints in the test method, and then I click Test->Debug->Tests in Current Context. I get the following screen shot.

    Then I try to debug it with “Step Into(F11)”, I find that actually your test method didn’t run the method “CheckEquivalence” in the Class1. That’s why you get this issue “Method 'Services.Class1.CheckEquivalence' not found.

    To create a unit test for this class method, I suggest you right click the method “CheckEquivalence” in the Class1, and then select “Create Unit Tests”, and then it will create the test method automatically. Then you could check it with different value.

    Best Regards,


    Jack Zhai [MSFT]
    MSDN Community Support | Feedback to us

  • Wednesday, May 30, 2012 12:27 PM
     
     Answered

    Hi

    Can you try below
    var equivalence = po.Invoke("CheckEquivalence", newType[] { a.GetType(), b.GetType() }, newObject[]{ (IEnumerable<Object>)a, (IEnumerable<Object>)b});

    Thanks

  • Wednesday, May 30, 2012 2:53 PM
     
     

    ...  "Then I try to debug it with “Step Into(F11)”, I find that actually your test method didn’t run the method “CheckEquivalence” in the Class1. That’s why you get thisissue “Method 'Services.Class1.CheckEquivalence' not found.”"  ...

    Well, duhh!  I know what the exception means. What I don't know is what is causing it, especially considering that both ILDASM and Reflector can "see" the CheckEquivalence method in the assembly.

    Also, the "Create Unit Tests" approach you recommended creates a unit test which uses the deprecated "Accessor" technique, which is not acceptable. 

    That's why I wrote my own unit test that uses PrivateObject.

    DadCat

  • Thursday, May 31, 2012 4:57 AM
    Moderator
     
     

    Hi DadCat,

    Glad to receive your reply.

    Like Dhruv’s reply, change that line code to the following code.

    var equivalence = po.Invoke("CheckEquivalence",new Type[] { a.GetType(), b.GetType() }, new Object[]{ (IEnumerable<Object>)a, (IEnumerable<Object>)b});

    It will work well.

    Best Regards,


    Jack Zhai [MSFT]
    MSDN Community Support | Feedback to us