这是我的例子:
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/