【问题标题】:How to mock PrivateObject in C#如何在 C# 中模拟 PrivateObject
【发布时间】:2017-08-03 03:26:19
【问题描述】:

我有这个代码:

    [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”方法,该方法返回一个布尔类型。我如何模拟 SometMetod,这样当我调用它时,他会返回我需要的东西?

【问题讨论】:

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


【解决方案1】:

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

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

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

可以测试私人会员,我并不是说它通常是错误的。不过,通常需要测试私有成员是糟糕的代码设计的标志。

私有方法和字段是实现细节,不应影响您的类的功能。不要将每个方法视为一个单元,而是将类视为一个单元。测试你的班级的行为,看看它做了它应该做的事情,而不是测试它是怎么做的。

对象结果 = privateObj.Invoke("DoSomething", txtBox, EventArgs.Empty); 您在privateObj 上调用DoSomething 方法,而不是在mockObj 上,未设置返回您“需要”的内容。

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

我想你可以做的是将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);
}

【讨论】:

  • PrivateObject 不是这样工作的。
  • @Nkosi 哦,哇,那是我的错。我更新了我的答案,即使它没有直接回答 OPs 问题
猜你喜欢
  • 2018-03-07
  • 2010-12-23
  • 2012-10-09
  • 1970-01-01
  • 1970-01-01
  • 2021-03-03
  • 2011-08-02
  • 2021-06-22
  • 2018-03-08
相关资源
最近更新 更多