简体   繁体   中英

How do I prepare test cases for Interfaces in JUnit?

Following is my code for interfaces, and three classes. I use JUNIT testing and the JUnit test class is also below. However I have no idea to pass the parameters from my concrete classes and use it in JUnit class.

Interface
ArithmeticSkeleton.java

public interface ArithmeticSkeleton {
    int operation(int a, int b);
}

Concrete Class For Division
Divide.java

public class Divide implements ArithmeticSkeleton{
    @Override
    public int operation(int a, int b) {
        return (a / b);
    }
}

Concrete Class For Multiplication
Multiply.java

public class Multiply implements ArithmeticSkeleton{
    @Override
    public int operation(int a, int b) {
        return (a * b);
    }
}

Concrete Class For Addition
Addition.java

 public class Addition implements ArithmeticSkeleton{
        @Override
        public int operation(int a, int b) {
            return (a + b);
        }
    }

JUnit Test Class
ArithmeticSkeletonTest.java

import static org.junit.Assert.*;
import java.util.Arrays;
import java.util.Collection;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
    public class ArithmeticSkeletonTest {
        public ArithmeticSkeleton asInterface;
        public Divide div;
        public ArithmeticSkeletonTest(ArithmeticSkeleton asInterface) {
            this.asInterface = asInterface;
    }
    @Parameterized.Parameters
    public static Collection<Object[]> testInstances(){
        return Arrays.asList(
                new Object[]{new Multiply()},
                new Object[]{new Addition()},
                new Object[]{new Subtraction()},
                new Object[]{new Divide()}
               );
    }   
}

how to test it on ArithmeticSkeletonTest.java

You don't test interfaces, you test implementations. In this case, the only contract you have for your interface is that it provide the function (int a, int b) -> int , with nothing more specific stated (in particular, is it okay for b to be zero?). The compiler ensures that this contract is upheld.

Instead, you should write a test for each implementing class , verifying that it performs the operation as expected.

Writers will sometimes say that you should test interfaces and not implementations. What they mean is that your test should interact with the API or contract, also known as the public interface of your code ( black-box testing ), and not examine the internal state of the class under test ( white-box testing ). This is not the same as writing all of your tests to a Java interface type.

For example, the contract of your Divide class says that it should return the quotient of a divided by b , and your test cases should confirm that this is what happens. However, it's up to your class to decide how to implement that. You can use the / operator, but you could also perform iterated subtraction, or you could use BigInteger.divide() . Any of these are correct (if not necessarily ideal) implementations of the Divide API, and your test should be satisfied with any of them.

You don't test interfaces, you test implementations. So if you have 5 classes that implement an interface, you will need 5 test classes, one for each implementation. You will find that those 5 classes have much code in common, because all will test that the implementations conform to the contract of the interface. I find it useful to extract that common code into parametric tests in a "test" class for the interface. It does not really "test the interface"; it tests "classes that implement the interface".

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM