2

我正在尝试在模拟对象上测试私有方法。请冷静下来,我知道你要把你的干草叉拿出来。

我很清楚要说的一切都可以通过对我大喊 REFACTOR 来回答。我只需要一个直接的答案。有人看着我的眼睛告诉我这是不可能的。这是一个无法通过谷歌搜索的问题,所以我只需要听到它。

这就是我正在处理的问题。

public class SecretManager
{
   protected virtual string AwfulString { get { return "AWFUL, AWFUL THING"; }

   public SecretManager()
   {
      //do something awful that should be done using injection
   }

   private string RevealSecretMessage()
   {
      return "don't forget to drink your ovaltine";
   }
}

这是我试图测试它。

var mgr = new Mock<SecretManager>();
mgr.Protected().SetupGet<string>("AwfulThing").Returns("");

var privateObj = new PrivateObject(mgr.Object);
string secretmsg = privateObj.Invoke("RevealSecretMessage");

Assert.IsTrue(secretmsg.Contains("ovaltine"));

和例外:

System.MissingMethodException: Method 'Castle.Proxies.SecretManagerProxy.RevealSecretMessage' not found

我正在尝试做的事情,尽管它很疯狂,可能吗?或者这对于单元测试来说是否过于狂妄?

4

3 回答 3

3

您正在尝试调用 Castle 创建的代理上的方法。代理将无法访问它继承自的类的私有方法,因为该方法是私有的。请记住 Castle.Proxies.SecretManagerProxy 实际上是 SecretManager 的子类。

您真的需要模拟 SecretManager 吗?我意识到您的代码是真实代码的精简摘要,但似乎您对模拟所做的唯一事情就是为您尝试测试的方法未使用的属性设置返回值.

于 2014-01-06T23:27:21.890 回答
2
var privateObj = new PrivateObject(mgr.Object, new PrivateType(typeof(SecretManager)));
string secretmsg = privateObj.Invoke("RevealSecretMessage");

它将通过PrivateType指定PrivateObject.

于 2016-10-09T09:26:01.730 回答
0

您的代码应该遵循您要测试的内容。您不需要模拟 SecretManager 和 SetGet "AwfulThing",因为您没有使用它。

var privateObj = new PrivateObject(new SecretManager());
string secretmsg = (string)privateObj.Invoke("RevealSecretMessage", new object[] {     });

Assert.IsTrue(secretmsg.Contains("ovaltine"));

但理想情况下,您不应该测试私有方法。解释见下面文章:

http://lassekoskela.com/thoughts/24/test-everything-but-not-private-methods/

于 2014-01-07T03:33:33.797 回答