我可能会问一些完全明显的事情。我在编写单元测试方面没有太多经验,而且出现了以下问题让我思考。
说,你有一个类,这个类有你想测试的方法。但是你可以一次测试一种方法吗?我想不是。为了测试该方法,您需要调用一个或多个其他方法。例如:
class MyClass {
int x;
void foo() { x = 4; }
boolean bar() { x = 3; }
boolean check() { return x == 4; }
}
为了测试foo和bar,我需要使用check(),另一方面,为了测试检查,我需要使用foo()或bar()。
说,我必须遵循测试用例:
class MyClassTest {
@Test
void testFoo() {
MyClass obj = new MyClass();
obj.foo();
assert obj.check();
}
}
现在让我们假设,我的同事改变了check()方法:
boolean check() { return x == 5; }
当然,testFoo()会失败,有人可能会认为foo方法存在问题。
所以这看起来像鸡蛋情况。人们通常如何解决这个问题?
答案 0 :(得分:5)
这里独立测试方法可能没什么意义,因为类的状态可以根据调用的方法顺序而改变。在这种情况下,我会确保行为 - 或状态转换 - 按预期工作。请参考以下三个正确指定类的行为的测试:
class WhenFooWasCalled {
@Test
public void ThenCheckShouldReturnTrue {
MyClass sut = new MyClass();
sut.foo();
assertTrue(sut.check());
}
}
class WhenBarWasCalled {
@Test
public void ThenCheckShouldReturnFalse {
MyClass sut = new MyClass();
sut.bar();
assertFalse(sut.check());
}
}
class WhenNothingWasCalled {
@Test
public void ThenCheckShouldReturnFalse {
MyClass sut = new MyClass();
assertFalse(sut.check());
}
}
更新:我添加了第三个测试用例:如果foo()和bar()都没有被调用,check()的行为如何。
答案 1 :(得分:2)
您不会为单个方法编写测试 - 您可以针对个别需求编写测试。在这种情况下,您的课程似乎有两个要求:
check
必须在最后一次调用true
时返回foo
”check
必须在最后一次调用false
时返回bar
”因此,您将编写两个单元测试,每个需求一个,以验证类是否正确地满足它(您可能想要制定第三个要求:check
在没有被调用时应该做什么)。当您的同事进行上述更改时,他既没有破坏foo
方法,也没有破坏check
方法。他破坏的是第一个要求。现在他必须以某种方式改变课程,以便它再次实现它。他如何完成这项工作(更改foo
,更改check
或两者)并不重要。
答案 2 :(得分:1)
这对于具有内部可变状态的类很常见。我认为你的问题减少了你的单元测试在给定的状态操作序列后表现正常。