我是否需要测试接口的每个实现来测试接口?

时间:2014-10-31 09:29:30

标签: java unit-testing interface

通常,我的应用程序中只有一个接口实现,并且在为接口编写测试时总是使用第一个实现。我们假设我有一个接口Destroyer和一个实现DestroyerImpl。然后我会在测试中使用该类:

class DestroyerTest 
{
    private Destroyer destroyer = new DestroyerImpl();

    @Test
    public void test() { ... }   
}

然后通过在接口测试中实例化来对该类进行隐式测试。 如果我写另一个实现类EpicDestroyer,我现在觉得我也必须测试它。

那么,我是否编写了两个测试类DestroyerImplTestEpicDestroyerTest,它们都使用不同的实现来测试相同的Destroyer接口?这不是多余的吗?我可以通过参数化来test each implementation in the same test suite。这是这样做的吗?

4 个答案:

答案 0 :(得分:4)

我认为你对测试的想法存在误解。

测试界面没有任何意义,因为它只是一个规范。只能测试实现。所以你应该测试所有的实现。但是,您可以从界面派生测试用例,因为所有实现都需要遵守其中的规范。因此,即使您有完全不同的实现,您也可以在这些实现之间共享测试。

在我看来,应该有以下测试类:

import java.util.List;

import org.junit.Assert;
import org.junit.Test;


public abstract class AbstractModifiableListTest
{

    protected abstract <T> List<T> createListInstanceUnderTest(T... elements);

    @Test
    public void removeDecreasesSizeByOne() {
        List<String> list = this.<String>createListInstanceUnderTest("a","b","c");
        int originalSize = list.size();

        list.remove( 0 );
        int newSize = list.size();

        Assert.assertEquals( originalSize - 1, newSize );
    }
}

包含测试接口规范的测试用例 - 在这种情况下为java.util.List。然后,通过实现抽象方法并可能添加依赖于实现的测试用例,测试实现然后参数化测试用例。

答案 1 :(得分:2)

我从不“测试”一个界面,因为没有什么可以测试的。界面描述了每个实现的服务,即合同。

因此,您必须测试此服务的每个实现,以确保每个人都能正确完成工作。

答案 2 :(得分:2)

我不会说接口可以被测试,因为它们提供抽象而不是实现。另一方面,测试需要确保是否实现了特定行为(并且行为在类中)。

  

那么,我是否编写了两个测试类DestroyerImplTest和EpicDestroyerTest,它们都使用不同的实现来测试相同的Destroyer接口?

我会说,

答案 3 :(得分:1)

如果您正在测试接口,那么使用单个实现测试它就足够了,因为接口不依赖于特定的实现。

当然,您可能希望测试每个实现,但是为了测试实现类,而不是接口本身。