Moq与PrivateObject不兼容吗?

时间:2014-01-06 22:46:17

标签: c# moq vs-unit-testing-framework privateobject.invoke

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

我很清楚所有要说的话都可以通过向我大喊大叫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

我正在尝试做什么,可能是疯了吗?或者这对单元测试来说太过狂妄了?

3 个答案:

答案 0 :(得分:3)

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

你真的需要一个模拟SecretManager吗?我意识到你的代码是真实代码的简洁摘要,但是你似乎唯一能做的就是设置一个属性的返回值,这个属性不是你试图测试的方法所使用的

答案 1 :(得分:1)

您的代码应该遵循您要测试的内容。您不需要模拟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/

答案 2 :(得分:1)

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

它可以为PrivateType指定PrivateObject