如何在 C# 中模拟 PrivateObject

How to mock PrivateObject in C#

我有这个代码:

    [TestMethod]
    public void TestMethod()
    {
        TextBox txtBox= new TextBox() { Text = "Test" };

        PrivateObject privateObj= new PrivateObject(someObject);
        var mockObj = new Mock<PrivateObject>();
        mockObj.Setup(x => x.Invoke("SomeMethod", It.IsAny<string>())).Returns(true);

        object result = privateObj.Invoke("DoSomething", txtBox, EventArgs.Empty);

        Assert.AreEqual(txtBox.Text, string.Empty);
    }

方法"DoSomething"调用了"SomeMethod"方法,其中returns是布尔类型。我怎样才能模拟 SometMetod,以便当我调用它时,他 returns 我需要什么?

抱歉,我应该更彻底地调查您的问题。我没有意识到 PrivateObject 是 .NET 框架中已经存在的 class。

我的回答不会直接回答你的问题,但无论如何我都会把它留在这里。我假设您使用 Moq,因此 classes 的以下部分不可用于模拟:

  • 非虚拟成员
  • 静态成员
  • 扩展方法
  • 密封classes
  • 的任何成员
  • 字段

私有成员可以测试,我不是说一般都是错的。不过,通常需要测试私有成员是错误代码设计的标志。

私有方法和字段是实现细节,不应影响您的 class 功能。不要将每个方法视为一个单元,而是将 class 视为一个单元。测试你的 class' 行为 并且它做了它应该做的事情而不是测试 它是如何做的

对象结果 = privateObj.Invoke("DoSomething", txtBox, EventArgs.Empty); 您在 privateObj 上调用 DoSomething 方法,而不是在 mockObj 上调用 未设置 到 return 您 "need".

你的单元测试应该实现什么? 被测系统的模拟行为有点矛盾,因为测试结果不能代表系统的实际行为。

我想你可以做的是将 SomeMethod 的功能从 PrivateObject 中提取到它的依赖项中,比方说 IHaveSomeMethod.

public interface IHaveSomeMethod {
    bool SomeMethod();
}

public class PrivateObject {
    private IHaveSomeMethod dependency;

    public PrivateObject(???SomeObject someObject???, IHaveSomeMethod ihsm) {
        // ...
        this.iHaveSomeMethod = ihsm;
        // ...
    }

    public void DoSometing() {
        // ...
        iHaveSomeMethod.SomeMethod();
        // ...
    }
}

那你可以这样测试

[TestMethod]
public void TestMethod()
{
    TextBox txtBox= new TextBox() { Text = "Test" };

    var mockObj = new Mock<IHaveSomeMethod>();
    mockObj.Setup(x => x.Invoke("SomeMethod", It.IsAny<string>())).Returns(true);

    var sut = new PrivateObject(???someObject???, mockObj.Object); // system under test
    object result = sut.Invoke("DoSomething", txtBox, EventArgs.Empty);

    Assert.AreEqual(txtBox.Text, string.Empty);
}