我正在TDD中编写一个新类(Derived
(,使用mockito,我有以下情况:
类基础:
public abstract class Base<T>{
//.......
protected final T baseCreate(T entity){
// implementation
}
}
类派生(这是我使用 TDD 编写的类(:
public class Derived extends Base<MyObject> {
//.......
public MyObject create(MyObject entity){
baseCreate(entity); //This is what I want the implementation to be
}
}
当我来编写测试时,会迫使我调用baseCreate
方法 - 我不明白如何做到这一点。有没有办法使用 mockito 验证 Derived
中的 create(...)
方法是否调用了 Base
类中的 baseCreate(...)
方法?
谢谢。
单元测试是用来测试类的行为,而不是它的实现。 所以你不应该关心Base
的baseCreate()
是否被显式调用,而应该从外部观察者的角度完全按照你期望的方式调用Derived
cerate()
。
提拉在大多数情况下都是正确的。 你想要测试的是,创建实际上做了你认为它应该做的事情,而不是它是如何做的。 你在这里的情况听起来像是,"我已经知道baseCreate做了我想让它做的事情,所以我不想重新测试它,只是它被调用了。 可能是这种情况,但如果是这样,那么你的超类实际上更像是一个合作者。 这是支持委派而不是继承的部分原因。 尽管如此,有时很难回过头来改变设计决策,所以你必须测试你所拥有的。
你仍然应该倾向于检查"create"在整体上是否做了你想要它做的事情,但你可能会遇到这样一种情况,即baseCreate确实做了很多需要大量协作者设置的东西,这使得测试变得困难和脆弱。 在这种情况下,您可能希望使用"间谍"。 间谍包装"真实"对象并委托给真实方法调用,除非您专门创建另一个期望。
如果你可以让baseCreate公开,你可以像这样使用Mockito:
@RunWith(MockitoJUnitRunner.class)
// We prepare PartialMockClass for test because it's final or we need to mock private or static methods
public class YourTestCase {
@Spy
private Derived classUnderTest = new Derived();
@Test
public void privatePartialMockingWithPowerMock() {
MyObject myObject = new MyObject();
when(classUnderTest.baseCreate(myObject)).thenReturn(myObject);
// execute your test
classUnderTest.create(myObject);
verify(classUnderTest).baseCreate(myObject);
}
}
如果你不能让baseCreate公开,我想你可以使用PowerMock。 它可以让您验证私有方法,但我认为它没有任何理由不能执行受保护的方法。
@RunWith(PowerMockRunner.class)
// We prepare PartialMockClass for test because it's final or we need to mock private or static methods
@PrepareForTest(Derived.class)
public class YourTestCase {
@Test
public void testCreate() {
Derived classUnderTest = PowerMockito.spy(new Derived());
MyObject myObject = new MyObject();
// use PowerMockito to set up your expectation
PowerMockito.doReturn(myObject).when(classUnderTest, "baseCreate", myObject);
// execute your test
classUnderTest.create(myObject);
// Use PowerMockito.verify() to verify result
PowerMockito.verifyPrivate(classUnderTest).invoke("baseCreate", myObject);
}
}
你说你正在使用TDD - 所以大概,有一些关于Derived
或Base
或两者所需行为的规范。 因此,您将围绕该规范编写一些测试。 这些测试不需要你做Derived
扩展Base
- 它们只需要每个类的某些行为;这将是您可以在不使用继承的情况下实现的行为。
一旦您的测试通过,那么下一阶段的TDD就会开始。 这是"重构"阶段,您可以在其中寻找类设计方式的改进。 这是您决定进行Derived
扩展Base
,并使create
方法调用baseCreate
的点。 奇妙的是,当你进行重构时,你已经进行了一些测试,以确保它正常工作。