单元测试,你可以测试一个单一的方法



我可能会问一些非常明显的问题。我在编写单元测试方面没有太多经验,下面的问题引起了我的思考。

比方说,你有一个类,这个类有你想要测试的方法。但是你能同时测试一种方法吗?我想不是。为了测试该方法,您需要调用一个或多个其他方法。例如:

class MyClass { 
    int x;
    void foo() { x = 4; }
    boolean bar() { x = 3; }
    boolean check() { return x == 4; }
}

为了测试foo和bar,我需要使用check(),另一方面,为了测试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方法有问题。

所以这看起来像是一个鸡蛋的情况。人们通常是如何解决这个问题的?

在这里独立测试方法可能没有多大意义,因为类的状态可以根据调用的方法的顺序而改变。在这种情况下,我会确保行为或状态转换按预期工作。请参考以下三个测试,它们正确地指定了类的行为:

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. "上次调用foo时,check必须返回true"
  2. "上次调用bar时,check必须返回false"

因此,您将编写两个单元测试,每个需求一个,以验证类是否正确地实现了它(您可能想要制定第三个需求:当两者都没有被调用时,check应该做什么)。当您的同事进行上述更改时,他既没有破坏foo方法,也没有破坏check方法。他打破的是第一个要求。现在,他不得不以某种方式改变这个类,以便它再次实现它。他如何做到这一点(更改foo、更改check或两者兼而有之)并不重要。

这在具有内部可变状态的类中很常见。我认为你的问题可以归结为你的单元测试在给定的状态操作序列之后表现正确。

最新更新