遇到“System.MissingMethodException:找不到方法”错误,使用PrivateObject。

10

基本上,我的一些测试通过了,而另一些测试失败了。根据Skeet先生的建议,我创建了一个完整的代码示例来确认我不是疯了。这是代码:

namespace ClassLibrary
{
    using System;

    public class Manager
    {
        private int SampleMethod(int id)
        {
            return id;
        }
    }
}

我的测试是:

namespace UnitTestProject
{
    using System;
    using Microsoft.VisualStudio.TestTools.UnitTesting;

    [TestClass]
    public class UnitTest
    {
        [TestMethod]
        public void TestPasses()
        {
            var privateInfo = new PrivateObject(new ClassLibrary.Manager());
            var actual = privateInfo.Invoke("SampleMethod", 1);
        }

        [TestMethod]
        public void TestErrorsOut()
        {
            var privateInfo = new PrivateObject(new ClassLibrary.Manager());
            var actual = privateInfo.Invoke("SampleMethod", 0);
        }

        [TestMethod]
        public void TestWorksAsWell()
        {
            var privateInfo = new PrivateObject(new ClassLibrary.Manager());
            privateInfo.Invoke("SampleMethod", new object[] { 0 });
        }

        [TestMethod]
        public void TestAlsoErrorsOut()
        {
            var privateInfo = new PrivateObject(new ClassLibrary.Manager());
            var types = new Type[] { typeof(int) };
            var actual = privateInfo.Invoke("SampleMethod", types, 0);
        }
    }
}

第一个测试(TestPasses())通过了。

第二个测试(TestErrorsOut())失败了,并出现以下错误: {"Method 'ClassLibrary.Manager.SampleMethod' not found."}

令人困惑的是,这个错误一直存在,但实际测试几乎相同。这毫无意义。我在VS2012 RC和VS2010上尝试过,结果相同。

我唯一能想到的是,“0”被转换为除int以外的其他类型,这意味着它找不到SampleMethod方法的签名?我尝试了第三个测试,明确传递了我要查找的类型(TestAlsoErrorsOut()),但结果也与相同的错误失败了。

有什么想法吗?谢谢。

添加编辑

使用Ian的建议,改用obj[]而不是params obj[]重载,它可以工作(测试TestWorksAsWell())。这解释了为令TestAlsoErrorsOut()失败,因为我使用的是params方法,它不能与Type[]一起使用。所以,这个问题已经解决了。但是,为什么?为什么params obj[]传递1时可以工作,但传递0时却不行?


3
你能展示一个简短但完整的程序来演示问题吗?这是将1误写为l之类的错别字吗? - Jon Skeet
为什么你想对私有方法进行单元测试? - Anuraj
2
@Anuraj - 我同意这篇关于“为什么”的文章,但我认为这不是讨论的场所。http://www.codeproject.com/Articles/9715/How-to-Test-Private-and-Protected-methods-in-NET。 - bryanjonker
3个回答

13
根据文档(http://msdn.microsoft.com/en-us/library/ms243710.aspx),参数应该作为对象数组传递。显式地传递一个对象数组似乎可以正常工作:
var actual = (int)privateInfo.Invoke("SampleMethod", new object[] {0});

将单独传递0似乎会导致编译器选择此重载函数。
Invoke(string name = "SampleMethod", System.Reflection.BindingFlags bindingFlags = Default, object[] args = {object[0]})

在我的情况下,我将其设置为var inputObj = new Object [2]; 即使我只传递一个输入参数.. 更改为var inputObj = new Object [1]; 解决了我的问题。 - Ziggler

1
伊恩·吉尔罗伊是正确的,但原因是因为PrivateObject.Invoke有许多签名之一是:Invoke(string name, Type[] types, object[] objects)。在我的情况下,我传递像Invoke("MethodName", null, null)这样的值,在这种情况下,C#编译器更喜欢提到的签名,而不是Invoke(string name, params object[] objects),这会导致错误。

1

当调用以下测试时,我遇到了System.MissingMethodException异常:

PrivateObject shadow = new PrivateObject(target);    
shadow.Invoke("PrivateMethod", new string[]{"arg1","arg2"});

目标的私有方法签名
private void PrivateMethod(string[] args)

我不得不在私有方法签名中添加参数以解决异常,如下所示:
private void PrivateMethod(params string[] args)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接