【问题标题】:Unit Testing a private method giving MissingMethodException [duplicate]单元测试给出 MissingMethodException 的私有方法 [重复]
【发布时间】:2019-10-07 22:36:10
【问题描述】:

我需要在我的单元测试中使用PrivateObject 调用private 方法。

private void UrgentBackupButton_Click(object parameter)
{
    // Do Something...
}

这是我的单元测试:

[TestMethod]
public void TestMethod1()
{
    //MainWindowViewModel main = new MainWindowViewModel();

    PrivateObject privateObj = new
    PrivateObject(typeof(MainWindowViewModel));

    privateObj.Invoke("UrgentBackupButton_Click",null);
}

privateObj.Invoke("UrgentBackupButton_Click",null) 给了我例外:

在 mscorlib.dll 中发生了“System.MissingMethodException”类型的异常,但未在用户代码中处理

有人可以帮忙吗?

【问题讨论】:

  • UrgentBackupButton_Click 似乎是一个事件处理程序(参数不正确,可能是由于复制/粘贴),单元测试不适用于 UI。要测试 UI,您必须使用一些自动化测试,这些测试将模拟用户(键入文本、移动鼠标​​、单击等)。考虑重构您的代码,使其具有带有公共方法的可单元测试模型,所有东西都在其中。
  • @Sinatr 是的,我找到了解决方案。这是不正确的参数。我没有直接将 null 作为参数传递,而是这样做了 - > Object paramaeter = null;和 privateObj.Invoke("UrgentBackupButton_Click",paramaeter)。这行得通!我知道这是小事。

标签: c# unit-testing


【解决方案1】:

单元测试应该测试 C# 类的公共接口。私有方法不能被其他类访问,因此测试类也不能访问是有意义的。

UrgentBackupButton_Click 似乎是一个事件处理程序,所以如果你想测试它,你必须找到一种手动触发事件而不是调用它的方法,但这取决于你正在使用的平台(WPF、UWP、 Xamarin 等)

【讨论】:

  • 这就是答案。附注:if you want to test it you have to find a way to trigger the event manually 如果您引发 WinForms 事件,这不再是单元测试,而是集成测试。单元测试应该将依赖项抽象掉(模拟或伪造),以便单元测试只能在内存中运行。
  • @LewsTherin 是的,它是一个 WPF 平台。如何触发事件 UrgentBackupButton_Click 你能告诉我。因为当我刚刚从私人公开然后将其称为单元测试时,我能够这样做。
【解决方案2】:

如果您发现自己需要对私有方法进行单元测试,一种解决方案是将该方法分离到它自己的类中,或者如果它是一个纯方法,也许可以分离到一个可以单独测试的静态方法中。

当您处理从 UI 调用的方法时,这也很有帮助。为了通过 UI 测试方法,您需要某种自动化集成测试。但是,如果您将相同的代码放在一个单独的类中,您现在可以在没有 UI 的情况下对其进行测试。现在是单元测试。

这就是为什么将尽可能多的应用程序逻辑从我们的 UI 中分离出来是有益的原因之一。编写调用方法的单元测试很容易。编写一个加载表单并按下按钮来调用完全相同的代码的集成测试并不容易。

我并不是建议我们应该对每个类中的每个私有方法都这样做。如果我们的类足够小,那么我们可以通过公共接口测试所有内容。但就其本质而言,表单将调用各种代码,将大量代码放在一个表单类的私有方法中是没有意义的。

我们可以使用依赖注入将代码移出表单,但我们也可以使用类似这样的简单方法:

private void UrgentBackupButton_Click(object parameter)
{
    var doesSomething = new ClassThatDoesSomething();
    doesSomething.DoSomething();
}

如果方法中的代码依赖于它从表单或事件参数中获取的值,您可以将这些值传递给类,无论是在其构造函数中还是作为方法参数。尽可能传递非 UI 类型。例如,如果方法需要文本框的值,则传递该值,而不是文本框本身。

所有这些都完成后,测试事件处理程序将变得不那么重要,因为它实际上不会做任何事情,除了调用另一个类中的另一个方法,并且该方法将进行单元测试。

【讨论】:

  • 是的,我试过了,它工作正常,但我不想从 UI 中分离代码或复制代码。
猜你喜欢
  • 2015-04-17
  • 1970-01-01
  • 2018-01-15
  • 2014-08-10
  • 1970-01-01
  • 2010-12-03
  • 1970-01-01
相关资源
最近更新 更多