java - 使用接口(interface)对工厂进行单元测试很困难

标签 java unit-testing interface junit mockito

最近我一直在督促自己学习越来越多的单元测试技术,但遇到了一些我无法弄清楚的事情——即如何开始。我正在尝试使用非常非常简单的单一方法对工厂进行单元测试。我已经使用示例名称简化了它,为您提供帮助。

public class HandlerFactory extends SecondHandlerFactory
{
    //To hold singleton of this class.
    private static SecondHandler factoryInstance = null;

    private HandlerFactory() throws HandlerCreationException
    {
            super();
    }

    protected InterfaceExample createSomethingByThisKey(String key) throws HandlerCreationException
    {
        InterfaceExample myNewHandler = null;

        if (StringFunctions.isEqualIgnoreCase(key, "Phone"))
        {
            myNewHandler = new PhoneHandler();
        }
    }
}

我在弄清楚如何设置此测试甚至落入 createSomethingByKey() 时遇到了很大的麻烦。即使这样,我什至不知道如何正确执行我的assertEquals()方法。

现在,我已经设置了一些东西来执行 createInstance();但对我来说,如何陷入这种困境似乎没有任何意义。添加的变量和接口(interface)让我很困惑。它看起来测试起来很简单,而且是一个非常非常短的类(class) - 但不接触这个(Java 甚至不是我的第一语言)对我来说是一堵难以逾越的墙)。

关于如何设置标准 JUnit 或 Mockito (实际上并不重要)有什么帮助吗?此外, protected 事实让我更加无能为力,因为正确的标准是在另一个包中进行单元测试。

最佳答案

老实说,我不确定你的困难是什么。我只能猜2:

  1. 您不知道要在这样的工厂测试什么。
  2. 您在测试 protected 方法时遇到问题

对于1,其实并不难,只要假设你正在测试的方法是公开的:

public class HandlerFactory extends SecondHandlerFactory
{
    public InterfaceExample createSomethingByThisKey(String key) throws HandlerCreationException
    {
        InterfaceExample myNewHandler = null;

        if (StringFunctions.isEqualIgnoreCase(key, "Phone"))
        {
            myNewHandler = new PhoneHandler();
        }
    }
}

此方法中的逻辑只是根据键创建一个处理程序实例。因此,您的测试应该旨在查看是否根据您的 key 创建了正确类型的处理程序。因此测试应该类似于:

@Test
testCreateSomethingByThisKeyGivenKeyForPhoneKey {
    InterfaceExample result = handelerFactory.createSomethingByThisKey("Phone");
    assertTrue("result is a PhoneHandler", result instanceof PhoneHandler);
}

@Test
testCreateSomethingByThisKeyGivenKeyForUnknownKey {
    InterfaceExample result = handelerFactory.createSomethingByThisKey("NONEXIST");
    assertNull("result", result);
}

对于问题 2(限制访问 protected 方法),您通常有 2 个选择: 我们通常将测试与被测系统 (SUT) 放在同一个包中,因此您应该能够调用 protected 方法。

您还可以选择创建一个特定于测试的子类 (TSS),它公开直接委托(delegate)给 SUT 中 protected 方法的方法(或覆盖以放松该方法的可见性),并针对 TSS 执行测试。当然,您应该确保您的 SUT 可以扩展。它可能看起来像这样

public class Sut {
  protected Foo methodToTest(Param param) {
    //....
  }
}

创建一个这样的 TSS:

public class SutTss extends Sut {
  @Override
  public Foo methodToTest(Param param) {  // visibility loosen
    return super.methodToTest(param);
  }
}

然后你可以自由地测试该 protected 方法(我相信在Java中很少使用它,因为我们总是可以通过将测试放在与SUT相同的包下来调用 protected 方法)

关于java - 使用接口(interface)对工厂进行单元测试很困难,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12311082/

相关文章:

c# - 预期在 mock 上调用一次,但为 0 次 With Moq

angular - 如何使用自定义 environment.test.ts 设置运行 Angular 7 单元测试?

c++ - Java 的最佳方法,如 C++ 中的适配器事件处理

java - 使用嵌套上限通配符时的不兼容类型

java - ByteArrayOutputStream 上传到服务器

ruby-on-rails - 如何在Rails功能测试中调用调试器?

java - 为什么直接从接口(interface)调用接口(interface)方法(没有实现)可以工作?

java - 除了标准化期望之外,接口(interface)(Java 中)还有其他用途吗?

java - setPreferredSize 不起作用

java - JAVA如何同时运行两个进程