我正在使用mockito在TDD中编写一个新类(Derived
),我有以下情况:
班级基础:
public abstract class Base<T>{
//.......
protected final T baseCreate(T entity){
// implementation
}
}
Class Derived(这是我使用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来验证create(...)
中的Derived
方法是否会调用baseCreate(...)
类中的Base
方法?
感谢。
答案 0 :(得分:5)
单元测试用于测试类的行为,而不是其实现。因此,您不应该关注Base
baseCreate()
被明确调用,而是调用Derived
的{{1}}完全按照您对外部观察者的观点所做的那样做
答案 1 :(得分:4)
Attila适用于大多数情况。你想要测试的是创造实际上做了你认为它应该做的事情,而不是它是如何做到的。你在这里的情况听起来像是,“我已经知道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);
}
}
答案 2 :(得分:1)
你说你正在使用TDD - 所以可能有一些Derived
或Base
或两者所需行为的规范。因此,您将围绕该规范编写一些测试。这些测试不要求你Derived
扩展Base
- 他们只需要每个类的某些行为;这将是你可以在不使用继承的情况下实现的行为。
一旦你的测试通过,那么TDD的下一阶段就会开始。这就是“重构”阶段,你可以在那里寻找类设计方式的改进。这是您决定Derived
延长Base
并使create
方法调用baseCreate
的点。美妙的是,当你做重构时,你已经进行了一些测试,以确保它能够正常工作。