如何对一个副作用是调用其他方法的方法进行单元测试? [英] How to unit test a method whose side effect is to call other method?

查看:68
本文介绍了如何对一个副作用是调用其他方法的方法进行单元测试?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的例子:

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. states是屏幕上不同位置,controller的视图可以假定这些位置.

My controller calls the doneWithCurrentState when a specific button is pressed. The states are different positions on screen that the views for that controller can assume.

如果当前状态为Normal,则该按钮将被隐藏.

If the current state is Normal, the button will be hidden.

如果在当前状态为Editing的情况下按下按钮,则会调用doneWithCurrentState方法(之所以说该方法,因为它实际上位于类``之内),并且应将控制器的视图状态更改为并使用ObjectDetails(只是一个具有用于更新Object的数据的结构)在database中更新Object,该数据应从控制器的视图(例如,文本字段,复选框等).

If the button is pressed with the current state as Editing, the doneWithCurrentState method (I say method because it is actually inside a class ``) will be called and it should change the controller's views state to Normal and update the Object in the database using the ObjectDetails (which is just a struct with data that will be used to update the Object) that should be retrieved from the controller's views (i.e., text fields, checkboxes, etc).

如果在当前状态为Focus的情况下按下按钮,则应该将其发送回Editing状态.

If the button is pressed with the current state as Focus, it should just send back to the Editing state.

我正在像这样对它进行单元测试:

I am unit testing it like this:

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方法一样.

But it seems wrong, it seems like I'm asserting a method call is made and then I'm making the call... it's just like asserting setter and getter methods.

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

What would be the right way of testing that doneWithCurrentState method? As part of the answer, I do accept something like "first you should refactor the method to better separate these concerns...".

谢谢.

推荐答案

如果您编写的不是测试优先级,那么一种明显的编写方式是编写一个案例,然后将其粘贴粘贴到下一个案例中.在这种情况下,一个容易犯的错误就是忘记将参数更新为updateViewState().因此(例如),您可能会发现自己从State.Focus转到State.Normal.尽管您编写的测试对您来说似乎有些微,但它可以防止此类错误.所以我认为它在做应该做的事.

If you wrote this not test-first, an obvious way to write it would be to write one case, then copy-paste into the next case. An easy mistake to make in that case would be to forget to update the parameter to updateViewState(). So (for instance) you might find yourself going from State.Focus to State.Normal. The test you've written, although it may seem weak to you, protects against mistakes of that nature. So I think it's doing what it should.

这篇关于如何对一个副作用是调用其他方法的方法进行单元测试?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆