java - 如何为接口(interface)编写junit测试?

标签 java unit-testing testing interface junit

为接口(interface)编写 junit 测试以便将它们用于具体实现类的最佳方法是什么?

例如你有这个接口(interface)和实现类:

public interface MyInterface {
    /** Return the given value. */
    public boolean myMethod(boolean retVal);
}

public class MyClass1 implements MyInterface {
    public boolean myMethod(boolean retVal) {
        return retVal;
    }
}

public class MyClass2 implements MyInterface {
    public boolean myMethod(boolean retVal) {
        return retVal;
    }
}

您将如何针对接口(interface)编写测试,以便将其用于类?

可能性一:

public abstract class MyInterfaceTest {
    public abstract MyInterface createInstance();

    @Test
    public final void testMyMethod_True() {
        MyInterface instance = createInstance();
        assertTrue(instance.myMethod(true));
    }

    @Test
    public final void testMyMethod_False() {
        MyInterface instance = createInstance();
        assertFalse(instance.myMethod(false));
    }
}

public class MyClass1Test extends MyInterfaceTest {
    public MyInterface createInstance() {
        return new MyClass1();
    }
}

public class MyClass2Test extends MyInterfaceTest {
    public MyInterface createInstance() {
        return new MyClass2();
    }
}

专业版:

  • 只需要实现一种方法

缺点:

  • 所有测试的被测类的依赖项和模拟对象必须相同

可能性2:

public abstract class MyInterfaceTest
    public void testMyMethod_True(MyInterface instance) {
        assertTrue(instance.myMethod(true));
    }

    public void testMyMethod_False(MyInterface instance) {
        assertFalse(instance.myMethod(false));
    }
}

public class MyClass1Test extends MyInterfaceTest {
    @Test
    public void testMyMethod_True() {
        MyClass1 instance = new MyClass1();
        super.testMyMethod_True(instance);
    }

    @Test
    public void testMyMethod_False() {
        MyClass1 instance = new MyClass1();
        super.testMyMethod_False(instance);
    }
}

public class MyClass2Test extends MyInterfaceTest {
    @Test
    public void testMyMethod_True() {
        MyClass1 instance = new MyClass2();
        super.testMyMethod_True(instance);
    }

    @Test
    public void testMyMethod_False() {
        MyClass1 instance = new MyClass2();
        super.testMyMethod_False(instance);
    }
}

专业版:

  • 对每个测试(包括依赖项和模拟对象)进行细粒度处理

缺点:

  • 每个实现测试类都需要编写额外的测试方法

您更喜欢哪种可能性或使用什么其他方式?

最佳答案

与@dlev 给出的备受赞誉的答案相反,有时像您建议的那样编写测试可能非常有用/很有必要。一个类的公共(public) API,通过其接口(interface)表示,是最重要的测试。话虽如此,我不会使用您提到的任何一种方法,而是使用 Parameterized改为测试,其中参数是要测试的实现:

@RunWith(Parameterized.class)
public class InterfaceTesting {
    public MyInterface myInterface;

    public InterfaceTesting(MyInterface myInterface) {
        this.myInterface = myInterface;
    }

    @Test
    public final void testMyMethod_True() {
        assertTrue(myInterface.myMethod(true));
    }

    @Test
    public final void testMyMethod_False() {
        assertFalse(myInterface.myMethod(false));
    }

    @Parameterized.Parameters
    public static Collection<Object[]> instancesToTest() {
        return Arrays.asList(
                    new Object[]{new MyClass1()},
                    new Object[]{new MyClass2()}
        );
    }
}

关于java - 如何为接口(interface)编写junit测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6724401/

相关文章:

java - SpringBoot : java. io.FileNotFoundException: 文件系统中无法解析文件[]以检查其内容长度

javascript - 如何测试 Jest 没有抛出异常?

unit-testing - 重构和测试驱动开发

testing - 以不同顺序执行时测试失败

java - POSITIVE_INFINITY 比较

java - 如何根据 HTML 展开下拉列表后单击复选框

java - Spring data mongodb搜索ISO日期

perl - 如何为同一发行版中的多个 Perl 模块设计单元测试?

python - 测试失败后自动关闭webdriver实例

angularjs - Protractor :在更新期间测试多个用户登录是否存在冲突