【问题标题】:How to create a state-based test for a method that calls other methods within the same class?如何为调用同一类中其他方法的方法创建基于状态的测试?
【发布时间】:2009-10-05 12:46:30
【问题描述】:

我有以下代码(我已经为这个问题简化了):

    public void HandleModeInit(int appMode){
        switch(appMode){
            Case 1:
                DoThis();
            Case 2:
                DoThat();
            Case 3:
                //no mode 3
            Case 4:
                DoSomethingElse();
            Case else:
                //do nothing
        }
    }

如何在不将其转换为集成测试(最终测试 DoThis()、DoThat() 和 DoSomethingElse() 正在做什么)的情况下对该方法进行单元测试?由于这些方法调用是针对与 HandleModeInit() 相同的类的方法,你将如何测试呢?

虽然理想情况下,方法调用会被提取到另一个类中,但如果这一举动没有任何意义呢?

【问题讨论】:

    标签: c# unit-testing xunit


    【解决方案1】:

    如果您可以控制传递给此方法的内容,那么我将传入一个接口,该接口将 appmode 作为参数,它是一个 AppModeImplementationFactory。这个工厂的目的是创建 AppModeImplementations。工厂如下所示:

    public class AppModeImplementationFactory: IAppModeFactory
    {
       public IAppModeImplementation Create(int appMode)
       {
          // switch case goes here to create the appropriate instance
       }
    }
    

    当您传入工厂时,这可以是一个模拟实例,您可以验证是否调用了 create 方法。如果要验证返回的实例类型,则需要在不同的测试下进行。这种方法将满足您因应用模式而执行逻辑的需求,因为工厂将根据应用模式返回您需要的实现。

    希望对你有帮助

    【讨论】:

      【解决方案2】:

      您可以创建一个名为 IAppMode 的接口,而不是使用 switch/case 语句来切换 appModes(我假设调用者可以决定要实例化哪个对象以正确实现 IAppMode,因为它们已经传入一个 int 到代表应用模式)。

      你的调用者会传入一个 IAppMode 对象,然后你的方法可以调用 IAppMode 的 DoThis() 方法。

      然后您可以创建一个实现 IAppMode 的虚拟对象,并在测试期间将其注入方法中。

      它使您的代码更简单(使用设计模式可以做到这一点)并且可以测试。

      【讨论】:

      • 在非简化版本中,appMode 是在整个应用程序中跟踪的东西 - 所以我无法更改它。所以我们本质上需要做的是执行方法因为 appmode,而不是on appmode(如果这有意义的话)。
      【解决方案3】:

      我意识到(尤其是你注意到它)代码被简化了,但是如果你不测试在这种情况下被调用的方法做了什么,你实际上在测试什么? appMode的值?

      如果不了解被调用方法内部发生的情况,很难(如果不是不可能的话)准确地解决这个问题。他们是否在进行任何可以模拟的出站调用(对外部服务、数据库等)?如果是这样,那可能是一条前进的道路。如果它们仅包含封装在类中的行为,也许它们会更改某些属性值,您可以在调用 HandleModeInit 返回时检查这些值?

      我通常不喜欢仅仅为了提高代码的可测试性而更改代码的设计,但一种方法是将类的公共接口与内部分离,然后将内部接口定义为,嗯,一个界面。这样你就可以开始嘲笑内部了。

      【讨论】:

      • DoThis()、DoThat() 和 DoSomethingElse() 方法调用是一个比较深的兔子洞。在内部,他们最终做了很多事情。根据调用哪个,它可能正在与设备交互、读取文件以及设置属性等。如果我们开始测试所有更改或设置的内容,我们会将其转换为集成测试,将正在发生的事情紧密耦合到测试中,因为我们将在所有不同的层进行验证。本质上,这是不能测试的东西,还是可以,但实际上应该作为集成测试进行测试?
      • 我可能会尝试在代码进行此类外部通信的所有地方进行剪辑,以可以模拟的方式包装该功能(因此,创建设备接口,文件阅读器等在某些工厂中,您可以在其中注入此功能的模拟版本。
      猜你喜欢
      • 2011-12-30
      • 2020-02-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多