4

我正在Derived使用 mockito 在 TDD 中编写一个新类(),我有以下情况:

类基:

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 来验证create(...)方法 inDerived调用类中的baseCreate(...)方法Base

谢谢。

4

3 回答 3

5

单元测试是为了测试类的行为,而不是它的实现。所以你不应该关心Base'sbaseCreate()是否被显式调用,而是调用Derived'scerate()是否完全符合你从外部观察者的角度所期望的

于 2012-05-17T15:14:41.843 回答
4

Attila 适用于大多数情况。您要测试的是 create 实际上做了您认为它应该做的事情,而不是它是如何做的。您在这里的情况听起来像,“我已经知道 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);
    }
}
于 2012-05-17T18:07:06.657 回答
1

Derived你说你正在使用 TDD - 所以大概,有一些关于其中一个或Base两个所需行为的规范。因此,您将围绕该规范编写一些测试。这些测试不需要你进行Derived扩展Base——它们只需要每个类的某些行为;这将是您可以在完全不使用继承的情况下实现的行为。

一旦您的测试通过,TDD 的下一个阶段就开始了。这是“重构”阶段,您可以在其中寻找类设计方式的改进。这是您决定进行Derived扩展Base并进行create方法调用的地方baseCreate。奇妙的是,当您进行重构时,您已经进行了一些测试,以确保它正常工作。

于 2012-05-18T08:34:43.427 回答