通常,我的应用程序中只有一个接口实现,并且在为接口编写测试时总是使用第一个实现。我们假设我有一个接口Destroyer
和一个实现DestroyerImpl
。然后我会在测试中使用该类:
class DestroyerTest
{
private Destroyer destroyer = new DestroyerImpl();
@Test
public void test() { ... }
}
然后通过在接口测试中实例化来对该类进行隐式测试。
如果我写另一个实现类EpicDestroyer
,我现在觉得我也必须测试它。
那么,我是否编写了两个测试类DestroyerImplTest
和EpicDestroyerTest
,它们都使用不同的实现来测试相同的Destroyer
接口?这不是多余的吗?我可以通过参数化来test each implementation in the same test suite。这是这样做的吗?
答案 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)
如果您正在测试接口,那么使用单个实现测试它就足够了,因为接口不依赖于特定的实现。
当然,您可能希望测试每个实现,但是为了测试实现类,而不是接口本身。