unit-testing - 如何对副作用是调用其他方法的方法进行单元测试?

标签 unit-testing testing mocking tdd

这是我的例子:

void doneWithCurrentState(State state) {
    switch (state) {
        case State.Normal:
            // this method is never actually called with State.Normal
            break;
        case State.Editing:
            controller.updateViewState(State.Normal);
            database.updateObjectWithDetails(controller.getObjectDetailsFromViews())
            break;
        case State.Focus:
            controller.updateViewState(State.Editing);
            break;
    }
}

我的 controller 在按下特定按钮时调用 doneWithCurrentState状态 是屏幕上该 Controller 的 View 可以采用的不同位置。

如果当前状态为Normal,按钮将被隐藏。

如果在当前状态为 Editing 的情况下按下按钮,将调用 doneWithCurrentState 方法(我说方法是因为它实际上在类 `` 中)并且它应该将 Controller 的 View 状态更改为 Normal 并使用 ObjectDetails (这是只是一个结构,其中包含将用于更新 Object 的数据,应该从 Controller 的 View (即文本字段、复选框等)中检索。

如果在当前状态为 Focus 时按下按钮,它应该返回到 Editing 状态。

我是这样进行单元测试的:

void testDoneWithCurrentStateEditing() {
    mockController.objectDetails = ...;

    myClass.doneWithCurrentState(State.Editing);

    AssertEqual(mockController.viewState, State.Normal, "controller state should change to Normal");

    AssertTrue(mockDatabase.updateObjectWithDetailsWasCalled, "updateObjectWithDetails should be called");
    AssertEqual(mockDatabase.updatedWithObjectDetail, mockController.objectDetails, "database should be updated with corresponding objectDetails");
}

void testDoneWithCurrentStateFocus() {
    myClass.doneWithCurrentState(State.Focus);

    AssertEqual(mockController.viewState, State.Editing, "controller state should change to Editing");

    AssertFalse(mockDatabase.updateObjectWithDetailsWasCalled, "updateObjectWithDetails should not be called");
}

但这似乎是错误的,似乎我正在断言进行了方法调用然后我正在进行调用......这就像断言 setter 和 getter 方法一样。

测试 doneWithCurrentState 方法的正确方法是什么? 作为答案的一部分,我确实接受类似“首先你应该重构方法以更好地分离这些问题......”之类的东西。

谢谢。

最佳答案

如果你写的不是测试先行的,一个明显的编写方法是写一个案例,然后复制粘贴到下一个案例中。在这种情况下,一个容易犯的错误是忘记将参数更新为 updateViewState()。所以(例如)您可能会发现自己从 State.Focus 转到 State.Normal。您编写的测试虽然对您来说可能看起来很弱,但可以防止出现这种性质的错误。所以我认为它正在做它应该做的事情。

关于unit-testing - 如何对副作用是调用其他方法的方法进行单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28840957/

相关文章:

ruby-on-rails - rails : Good process for adding tests retroactively?

java - stub 方法中的 Mockito 异常

android - 测试 MediaBrowserServiceCompat 实现

java - 单元测试模拟服务实现

unit-testing - RhinoMock vs. TypeMock vs. NUnit 的 Mocking?

javascript - 传递给组件的 ReactJS/Jest : How to test/mock a function,

matlab - 扩展 LIBSVM 的测试数据 : MATLAB implementation

python - 如何为 Django 项目创建模拟 LDAP 服务器?

java - 模拟 Java Web 服务的最佳方式

c# - 如何使用 Watin 获取元素列表?