繁体   English   中英

如何测试类方法是否正在从类的私有对象之一调用另一个方法

[英]How can I test if a class method is calling another method from one of the classes's private objects

我正在尝试为一个项目创建单元测试。 在我的项目中,我有一个菜单类和一个VerticalOptions类。

我的菜单类有一个私有的VerticalOptions对象和一个公共的handleInput方法。 当我调用菜单的handleInput(key)方法时,根据我提供的键,它会执行不同的操作,即调用VerticalOptions对象的不同方法。

我想做一个unitTest来查看被调用的方法是否正确,我该怎么做?

我尝试将Mockito间谍添加到菜单中,但是由于我想测试被调用的方法是否是私有VerticalOptions对象中的方法,因此它实际上不起作用。

在使用getVerticalOptions方法获取间谍程序之后,我还尝试了将间谍放在VerticalOptions对象上,但是它也不起作用。

public void handleInput(InputKey key)
{
    switch (key) {
        case S:
        case DOWN:
            optionsInterface.cycleDown();
            break;
        case W:
        case UP:
            optionsInterface.cycleUp();
            break;
        case SPACE:
        case ENTER:
            optionsInterface.select();
            break;
        default:
            break;
    }
}


@Test
public void testInput() {
    MainMenu menu = new MainMenu(game);
    VerticalButtonInterface buttonInterface = menu.getOptionsInterface();
    VerticalButtonInterface spy = spy(buttonInterface);

    menu.handleInput(InputKey.DOWN);
    verify(spy, times(1)).cycleDown();
}

这是我的测试失败:

想要但不被调用:verticalButtonInterface.cycleDown(); ->在MenuTest.testInput(MenuTest.java:60)上,实际上与该模拟的交互为零。

我将为您提供另一种观点。 我已经看到很多人走错了道路,当您这样做时,其他所有事情都会变得难以执行/测试,这正是您现在正在做的事情。

从这里开始,您要达到什么目标?

我想测试并确保某种方法被称为...

这是一件好事吗? 什么不是单元测试? 那就是对代码的深入了解。

为什么? 因为每次您对代码进行微小的更改时,由于这些深厚的知识,您都必须更改测试。 如果您有1000项测试,那您将步履艰难。

好的,现在我们知道了问题所在,那么如何解决呢? 好吧,首先让我们确保无需进行深入的代码测试就可以进行测试。

我们该怎么做? 好吧,假设您的代码添加了一个额外的步骤,即设置状态的标志。 您可能有一个存储结果状态的标志...

您有3个要调用的方法,所以您将需要3个不同的状态,因此请创建一个反映该变量的变量,它可以是字符串,枚举或其他使您满意的变量。

例如,假设我们创建一个具有3个可能值的字符串:cycleDown,cycleUp和select。

您的代码开始看起来像:

public string handleInput(InputKey key)
{
      String state = determineState(key);
      SomeType someResult = executeActionForState(state);
}

public String determineState(string key)
{

    String state = "";
     switch (key) {
    case S:
    case DOWN:
        state = "cycleDown";
        break;
    case W:
    case UP:
        state = "cycleUp";
        break;
    case SPACE:
    case ENTER:
        state = "select";
        break;
    default:
        break;
}

return state;
}

public void executeActionForState(string state)
{
     if ( state == "cycleup" ) {
     }

     etc etc
}

现在,我不一定要像这样编写您的示例,这有点强迫,它取决于您对代码执行的其他操作,但这只是为了说明如何将功能与UI方面分开。

我可以轻松地测试状态方法,可以更改其代码,而不必更改测试,因为该测试将查看输入和输出,而不是如何实现。

单元测试是关于功能的,它涉及的是简单的测试,一旦创建就不需要进行更改。 验证方法已被调用不会给您带来任何价值,因为您不知道该方法以后会做什么。

您可以通过其他方式测试UI内容,而单元测试仅与正确的功能有关。 如果您没有明确区分,那么您将很难维护测试,在您放弃之前,它将越来越难。

您将测试您是否获得了正确的状态,然后测试了cycleUp方法根据您的要求执行了正确的操作,这就是您知道每个部分独立工作的方式。 稍后,您开始研究集成测试,自动UI测试,但这是不同的。 保持单元测试的目的,保持简单,使其不与其他代码绑定,然后一切都变得简单。 您无需进行太多模拟,也不必为复杂的设置担心太多,也不必每次代码更改时都更改测试。

现在,要解决问题的最后一部分,私有方法,您可以通过观察它们的输出来对其进行测试。 您必须在类中拥有一些公共的东西,这些东西在调用私有方法时会发生变化。 所以测试一下。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM