How can I enforce that my test class covers a particular interface?
Also is there a convention for writing overloaded test methods, so the names are consistent (my current technique is something like: methodName + parameter1Type + parameter2Type + ...)?
I'm hoping the second question will be covered/avoided if there is a good way to do the first.
My issue is I have classes which implement a number of interfaces. Since I'm testing Spring injected service classes, everything has at least one interface.
Anyways say I have a class that implements:
public interface MyInterface{
int doFoo(int input);
int doBar(int input);
}
Lets say MyInterfaceImpl, implements this interface.
Now my test class will look something like:
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class MyInterfaceImplTest{
private MyInterface = new MyInterfaceImpl(); //could inject it...
#Test
public void doFooTest(){
//content of test not relevant
}
#Test
public void doBarTest(){
//content of test not relevant
}
}
Now the above isn't to bad in terms of size, but it's hard to know if I've covered all the testing in larger classes, I could have missed one. Also I find it anyoying to create method names for overloaded methods. I could also add functionality to a class and possibly missed it. If I'm doing TDD this would be nearly impossible but I'd still like to be sure. What I've been tempted to write is...
public class MyInterfaceImplTest implements MyInterface{
And then I'd like to stick #Test in front of each method. Of course this isn't going to work because, well the test needs to put the values in. But using implements lets the IDE add the methods and it enforces that the full interface has been implemented. To be clear I know I am not looking to actually implement the interface in the test, but I think it could speed up development if I could do something like this.
To me this depends on what you mean by "enforce" and "covers a particular interface".
If your interface methods imply certain "contracts" (e.g. java.util.Collection.add() returns true if the receiving collection was modified as the result of the call), that you want to ensure are upheld by implementers of the interface, you can create a Contract Test.
If you want to see that all methods of a test subject are exercised by a particular test class, you can run the test under a code coverage tool like EMMA or Cobertura and ensure the results are to your liking.
You should probably look into parameterized testing. Here is what it would look like with TestNG:
#Test(dataProvider = "dp")
public testInterface(StrategyInterface si) {
// will be invoked twice, one with each implementation
}
#DataProvider
static public Object[][] dp() {
return new Object[][] {
new Object[] { new Strategy1Impl() },
new Object[] { new Strategy2Impl() },
};
}
Related
Usually, I only have one implementation of an interface in my application and that first implementation is always used when writing the tests for the interface. Let's say I have an interface Destroyer and an implementation DestroyerImpl. Then I would use that class in the test:
class DestroyerTest
{
private Destroyer destroyer = new DestroyerImpl();
#Test
public void test() { ... }
}
The class is then implicitly tested by being instantiated in the testing of the interface.
If I write another implementation class EpicDestroyer I now feel like I have to test that as well.
So, do I write two test classes DestroyerImplTest and EpicDestroyerTest that both test the same Destroyer interface with different implementations? Wouldn't that be redundant? I could test each implementation in the same test suite by parameterizing it. Is this the way to do it?
I think there is a misconception in your thinking about testing.
There is no sense in testing an interface as it is only a specification. Only implementations can be tested. So you should test all implementations. However you may be able to derive test cases from the interface as all implementations need to adhere to the specifications in there. So even though you have completely different implementations you may share tests between those.
In my mind there should be test classes like the following:
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 );
}
}
that contain the test cases that test the specification of the interface - java.util.List in this case. Tests for Implementations then parameterize the test case by implementing abstract methods and possibly adding implementation dependent test cases.
I never "test" an interface because there is nothing to test. The interface describe the service each implentation as to deliver, Its the contract.
So you have to test each implementation of this service to ensure everybody does the job correctly.
I wouldn't say that interfaces can be tested, because they provide abstraction and not implementation. Tests, on the other hand, need to ensure if a specific behavior is implemented (and the behavior is in the classes).
So, do I write two test classes DestroyerImplTest and EpicDestroyerTest that both test the same Destroyer interface with different implementations?
I would say, yes.
If you are testing the interface, it should be sufficient to test it with a single implementation, since the interface doesn't depend on a specific implementation.
Of course you'll probably want to test each implementation, but for the purpose of testing the implementing class, not the interface itself.
I am trying to write contract tests for some widely used interfaces:
Along the lines of:
public abstract class MyInterfaceContractTest extends TestCase {
private MyInterface _toTest;
public void setUp(){
_toTest = getTestableImplementation();
}
protected abstract MyInterface getTestableImplementation();
public void testContract(){
}
}
...and...
public class MyInterfaceImplementationTest extends MyInterfaceContractTest {
protected MyInterface getTestableImplementation(){
return new MyInterfaceImplementation(...);
}
}
However, I want to be able to test multiple instances of MyInterfaceImplementation. In my use case, this is an immutable object containing a collection of data (with accessors specified as per the interface MyInterface), and it might be empty, or have a small amount of data, or even lots of data.
So the question is, how can I test multiple instances of my implementations?
At the moment, I have to initialise the implementation to pass it into the abstract contract test. One approach would be to have multiple test classes for each implementation, where each test class tests a particular instance of that implementation - but that then seems a bit voluminous and difficult to keep track of.
FWIW, I'm using JUnit 3.
Generally the approach would be to use a "testable" subclass of the abstract class to test all the functionality of the abstract class in one test. Then write a separate test for each concrete implementation testing just the methods defined / implemented in the concrete class (don't retest the functionality in the concrete class).
If I've understood your need correctly, you want to run the same test method or methods with multiple implementations of the same interface.
I don't know how to do this very nicely in JUnit 3.
If you're willing to upgrade to JUnit 4, this can be done by using a parametrized test.
For the simple example of running a single test method on two implementations of an interface, your test code could look something like this:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.util.Arrays;
import java.util.Collection;
import static junit.framework.Assert.assertEquals;
// Tell JUnit4 to run it as a parametrized test.
#RunWith(Parameterized.class)
public class MyInterfaceContractTest {
private MyInterface _toTest;
// Load the test data into your test instance via constructor
public MyInterfaceContractTest(MyInterface impl) {
this._toTest = impl;
}
// Supply the test data, in this example just the two implementations you want to test.
#Parameterized.Parameters
public static Collection<Object[]> generateData() {
return Arrays.asList(new Object[]{new MyInterfaceImpl1()}, new Object[]{new MyInterfaceImpl2()});
}
#Test
public void testContract(){
// assert whatever, using your _toTest field
}
}
On running this test, JUnit will run the test twice, calling the constructor with the successive entries in the parameter list.
If you have more complex things, like different expectations for the different implementations, the data generation could return lists of Object arrays that contain multiple elements, and the constructor would then take a corresponding multiple arguments.
If you need to reinitialize the object under test between test methods, you might also want to use the trick I described in this related question.
I believe similar things are possible in TestNG, which might be another choice for your upgrade path.
I find myself writing lots and lots of boiler plate tests these days and I want to optimize away a lot of these basic tests in a clean way that can be added to all the current test classes without a lot of hassle.
Here is a basic test class:
class MyClassTest {
#Test
public void doesWhatItDoes() {
assertEquals("foo",new MyClass("bar").get());
}
}
Lets say if MyClass implements Serializable, then it stands to reason we want to ensure that it really is serializable. So I built a class which you can extend which contains a battery of standard tests which will be run along side the other tests.
My problem is that if MyClass does NOT implement Serializable for instance, we still have a serialization test in the class. We can make it just succeed for non-serializable classes but it still sticks around in the test list and once this class starts to build it will get more and more cluttered.
What I want to do is find a way to dynamically add those tests which are relevant to already existing test classes where appropriate. I know some of this can be done with a TestSuit but then you have to maintain two test classes per class and that will quickly become a hassle.
If anyone knows of a way to do it which doesn't require an eclipse plug-in or something like that, then I'd be forever grateful.
EDIT: Added a brief sample of what I described above;
class MyClassTest extend AutoTest<MyClass> {
public MyClassTest() {
super(MyClass.class);
}
#Test
public void doesWhatItDoes() {
assertEquals("foo",new MyClass("bar").get());
}
}
public abstract class AutoTest<T> {
private final Class<T> clazz;
protected AutoTest(Clazz<T> clazz) {
super();
this.clazz = clazz;
}
#Test
public void serializes() {
if (Arrays.asList(clazz.getInterfaces()).contains(Serializable.class)) {
/* Serialize and deserialize and check equals, hashcode and other things... */
}
}
}
Two ideas.
Idea 1:
Use Assume
A set of methods useful for stating assumptions about the conditions in which a test is meaningful. A failed assumption does not mean the code is broken, but that the test provides no useful information. The default JUnit runner treats tests with failing assumptions as ignored.
#Test
public void serializes() {
assumeTrue(Serializable.class.isAssignableFrom(clazz));
/* Serialize and deserialize and check equals, hashcode and other things... */
}
Idea 2: implement your own test runner.
Have a look at #RunWith and Runner at http://junit.sourceforge.net/javadoc/
Most pragmatic solution within existing capabilities of JUnit is to have a single annotated test:
#Test
void followsStandardJavaLibraryProtocols() {
if (implementsInterface(Serializable.class) {
testSerialisableInterface
...
Breaks various abstract principles of TDD, but works, with no unnecessary cleverness.
Perhaps, instead of a flat list of test cases, Junit could be extended to have more straightforward support for this kind of heirarchical test with subtests. Something like a #Subtest annotation that identified a test not to be invoked directly, instead adding a node to the result tree when it was, and with what arguments.
Your approach seems like a valid one to me. I don't have a problem with it.
I do this slightly differently. I would create another single test which tests all of your Serializable classes:
public class SerializablesTest {
#Test
public void serializes() {
testSerializable(MyClass.class);
testSerializable(MyClass2.class);
}
private testSerializable(Class clazz) {
// do the real test here
/* Serialize and deserialize and check equals, hashcode and other things... */
}
}
What does this give you? For me, explicitness. I know that I am testing class MyClass for serializability. There isn't any magic involved. You don't need to pollute your other tests.
If you really need to test all your classes which implement Serializable, you can find all of your classes using reflection.
I use this approach a lot, using reflection to build objects. For instance, I can test that all fields are persisted to & reread from a database correctly. I use this sort of thing all of the time.
Before asking question, let me explain the current setup:
I have an service interface, say Service, and one implementation, say ServiceImpl. This ServiceImpl uses some other services. All the services are loaded as bean by spring.
Now, I want to write junit test cases for the ServiceImpl. For the same, I use the applicationContext to get the Service bean and then call different methods on it to test them.
All looks fine for the public methods but how do I write test cases for private methods? Because we might not have the same private methods for different implementations?
Can anyone help me here on what should be preferred way of writing test cases?
The purist answer is that private methods are called that for a reason! ;-)
Turn the question around: given only the specification of a (publicly-accessible) interface, how would you lay out your test plan before writing the code? That interface describes the expected behavior of an object that implements it; if it isn't testable at that level, then there's something wrong with the design.
For example, if we're a transportation company, we might have these (pseudo-coded) interfaces:
CapitalAsset {
Money getPurchaseCost();
Money getCurrentValue();
Date whenPurchased();
...
}
PeopleMover {
Weight getVehicleWeight();
int getPersonCapacitly();
int getMilesOnFullTank();
Money getCostPerPersonMileFullyLoaded(Money fuelPerGallon);
...
}
and might have classes including these:
Bus implements CapitalAsset, PeopleMover {
Account getCurrentAdvertiser() {...}
boolean getArticulated() {...}
...
}
Computer implements CapitalAsset {
boolean isRacked() {...}
...
}
Van implements CapitalAsset, PeopleMover {
boolean getWheelchairEnabled() {...}
...
}
When designing the CapitalAsset concept and interface, we should have come to agreement with the finance guys as to how any instance of CapitalAsset should behave. We would write tests against CapitalAsset that depend only on that agreement; we should be able to run those tests on Bus, Computer, and Van alike, without any dependence on which concrete class was involved. Likewise for PeopleMover.
If we need to test something about a Bus that is independent from the general contract for CapitalAsset and PeopleMover then we need separate bus tests.
If a specific concrete class has public methods that are so complex that TDD and/or BDD can't cleanly express their expected behavior, then, again, that's a clue that something is wrong. If there are private "helper" methods in a concrete class, they should be there for a specific reason; it should be possible to ask the question "If this helper had a defect, what public behavior would be affected (and how)?"
For legitimate, inherent complexity (i.e. which comes from the problem domain), it may be appropriate for a class to have private instances of helper classes which take on responsibility for specific concepts. In that case, the helper class should be testable on its own.
A good rule of thumb is:
If it's too complicated to test, it's too complicated!
Private methods should be exercised through the public interface of a class. If you have multiple implementations of the same interface, I'd write test classes for each implementation.
You have written multiple implementations of an interface and want to test all implementations with the same JUnit4-test. In the following you will see how you can do this.
Also there is an example that shows how to get a new instance for each test case.
Example Code
Before I start explaining things here’s some example code for the java.util.list interface:
public class ListTest {
private List<Integer> list;
public ListTest(List<Integer> list){
this.list = list;
}
#Parameters
public static Collection<Object[]> getParameters() {
return Arrays.asList(new Object[][] {
{ new ArrayList<Integer>() },
{ new LinkedList<Integer>()}
});
}
#Test
public void addTest(){
list.add(3);
assertEquals(1, list.size());
}
}
I think you should split the testcases.
First you test the class which is calling the different implementations of the interfaces. This would mean you are testing the public methodes.
After this you test the interface implementaion classes in another testcase. Their you can call the methode with reflection.
I found an interesting article on how to test private methods with JUNIT at http://www.artima.com/suiterunner/privateP.html
So, I assume we should prefer testing private methods indirectly by testing the public methods. Only in exceptional circumstances, we should think of testing private methods.
I was wondering how to unit test abstract classes, and classes that extend abstract classes.
Should I test the abstract class by extending it, stubbing out the abstract methods, and then test all the concrete methods? Then only test the methods I override, and test the abstract methods in the unit tests for objects that extend my abstract class?
Should I have an abstract test case that can be used to test the methods of the abstract class, and extend this class in my test case for objects that extend the abstract class?
Note that my abstract class has some concrete methods.
There are two ways in which abstract base classes are used.
You are specializing your abstract object, but all clients will use the derived class through its base interface.
You are using an abstract base class to factor out duplication within objects in your design, and clients use the concrete implementations through their own interfaces.!
Solution For 1 - Strategy Pattern
If you have the first situation, then you actually have an interface defined by the virtual methods in the abstract class that your derived classes are implementing.
You should consider making this a real interface, changing your abstract class to be concrete, and take an instance of this interface in its constructor. Your derived classes then become implementations of this new interface.
This means you can now test your previously abstract class using a mock instance of the new interface, and each new implementation through the now public interface. Everything is simple and testable.
Solution For 2
If you have the second situation, then your abstract class is working as a helper class.
Take a look at the functionality it contains. See if any of it can be pushed onto the objects that are being manipulated to minimize this duplication. If you still have anything left, look at making it a helper class that your concrete implementation take in their constructor and remove their base class.
This again leads to concrete classes that are simple and easily testable.
As a Rule
Favor complex network of simple objects over a simple network of complex objects.
The key to extensible testable code is small building blocks and independent wiring.
Updated : How to handle mixtures of both?
It is possible to have a base class performing both of these roles... ie: it has a public interface, and has protected helper methods. If this is the case, then you can factor out the helper methods into one class (scenario2) and convert the inheritance tree into a strategy pattern.
If you find you have some methods your base class implements directly and other are virtual, then you can still convert the inheritance tree into a strategy pattern, but I would also take it as a good indicator that the responsibilities are not correctly aligned, and may need refactoring.
Update 2 : Abstract Classes as a stepping stone (2014/06/12)
I had a situation the other day where I used abstract, so I'd like to explore why.
We have a standard format for our configuration files. This particular tool has 3 configuration files all in that format. I wanted a strongly typed class for each setting file so, through dependency injection, a class could ask for the settings it cared about.
I implemented this by having an abstract base class that knows how to parse the settings files formats and derived classes that exposed those same methods, but encapsulated the location of the settings file.
I could have written a "SettingsFileParser" that the 3 classes wrapped, and then delegated through to the base class to expose the data access methods. I chose not to do this yet as it would lead to 3 derived classes with more delegation code in them than anything else.
However... as this code evolves and the consumers of each of these settings classes become clearer. Each settings users will ask for some settings and transform them in some way (as settings are text they may wrap them in objects of convert them to numbers etc.). As this happens I will start to extract this logic into data manipulation methods and push them back onto the strongly typed settings classes. This will lead to a higher level interface for each set of settings, that is eventually no longer aware it's dealing with 'settings'.
At this point the strongly typed settings classes will no longer need the "getter" methods that expose the underlying 'settings' implementation.
At that point I would no longer want their public interface to include the settings accessor methods; so I will change this class to encapsulate a settings parser class instead of derive from it.
The Abstract class is therefore: a way for me to avoid delegation code at the moment, and a marker in the code to remind me to change the design later. I may never get to it, so it may live a good while... only the code can tell.
I find this to be true with any rule... like "no static methods" or "no private methods". They indicate a smell in the code... and that's good. It keeps you looking for the abstraction that you have missed... and lets you carry on providing value to your customer in the mean time.
I imagine rules like this one defining a landscape, where maintainable code lives in the valleys. As you add new behaviour, it's like rain landing on your code. Initially you put it wherever it lands.. then you refactor to allow the forces of good design to push the behaviour around until it all ends up in the valleys.
Write a Mock object and use them just for testing. They usually are very very very minimal (inherit from the abstract class) and not more.Then, in your Unit Test you can call the abstract method you want to test.
You should test abstract class that contain some logic like all other classes you have.
What I do for abstract classes and interfaces is the following: I write a test, that uses the object as it is concrete. But the variable of type X (X is the abstract class) is not set in the test. This test-class is not added to the test-suite, but subclasses of it, that have a setup-method that set the variable to a concrete implementation of X. That way I don't duplicate the test-code. The subclasses of the not used test can add more test-methods if needed.
To make an unit test specifically on the abstract class, you should derive it for testing purpose, test base.method() results and intended behaviour when inheriting.
You test a method by calling it so test an abstract class by implementing it...
If your abstract class contains concrete functionality that has business value, then I will usually test it directly by creating a test double that stubs out the abstract data, or by using a mocking framework to do this for me. Which one I choose depends a lot on whether I need to write test-specific implementations of the abstract methods or not.
The most common scenario in which I need to do this is when I'm using the Template Method pattern, such as when I'm building some sort of extensible framework that will be used by a 3rd party. In this case, the abstract class is what defines the algorithm that I want to test, so it makes more sense to test the abstract base than a specific implementation.
However, I think it's important that these tests should focus on the concrete implementations of real business logic only; you shouldn't unit test implementation details of the abstract class because you'll end up with brittle tests.
one way is to write an abstract test case that corresponds to your abstract class, then write concrete test cases that subclass your abstract test case. do this for each concrete subclass of your original abstract class (i.e. your test case hierarchy mirrors your class hierarchy). see Test an interface in the junit recipies book: http://safari.informit.com/9781932394238/ch02lev1sec6. https://www.manning.com/books/junit-recipes or https://www.amazon.com/JUnit-Recipes-Practical-Methods-Programmer/dp/1932394230 if you don't have a safari account.
also see Testcase Superclass in xUnit patterns: http://xunitpatterns.com/Testcase%20Superclass.html
I would argue against "abstract" tests. I think a test is a concrete idea and doesn't have an abstraction. If you have common elements, put them in helper methods or classes for everyone to use.
As for testing an abstract test class, make sure you ask yourself what it is you're testing. There are several approaches, and you should find out what works in your scenario. Are you trying to test out a new method in your subclass? Then have your tests only interact with that method. Are you testing the methods in your base class? Then probably have a separate fixture only for that class, and test each method individually with as many tests as necessary.
This is the pattern I usually follow when setting up a harness for testing an abstract class:
public abstract class MyBase{
/*...*/
public abstract void VoidMethod(object param1);
public abstract object MethodWithReturn(object param1);
/*,,,*/
}
And the version I use under test:
public class MyBaseHarness : MyBase{
/*...*/
public Action<object> VoidMethodFunction;
public override void VoidMethod(object param1){
VoidMethodFunction(param1);
}
public Func<object, object> MethodWithReturnFunction;
public override object MethodWithReturn(object param1){
return MethodWihtReturnFunction(param1);
}
/*,,,*/
}
If the abstract methods are called when I don't expect it, the tests fail. When arranging the tests, I can easily stub out the abstract methods with lambdas that perform asserts, throw exceptions, return different values, etc.
If the concrete methods invoke any of the abstract methods that strategy won't work, and you'd want to test each child class behavior separately. Otherwise, extending it and stubbing the abstract methods as you've described should be fine, again provided the abstract class concrete methods are decoupled from child classes.
I suppose you could want to test the base functionality of an abstract class... But you'd probably be best off by extending the class without overriding any methods, and make minimum-effort mocking for the abstract methods.
One of the main motivations for using an abstract class is to enable polymorphism within your application -- i.e: you can substitute a different version at runtime. In fact, this is very much the same thing as using an interface except the abstract class provides some common plumbing, often referred to as a Template pattern.
From a unit testing perspective, there are two things to consider:
Interaction of your abstract class with it related classes. Using a mock testing framework is ideal for this scenario as it shows that your abstract class plays well with others.
Functionality of derived classes. If you have custom logic that you've written for your derived classes, you should test those classes in isolation.
edit: RhinoMocks is an awesome mock testing framework that can generate mock objects at runtime by dynamically deriving from your class. This approach can save you countless hours of hand-coding derived classes.
First if abstract class contained some concrete method i think you should do this considered this example
public abstract class A
{
public boolean method 1
{
// concrete method which we have to test.
}
}
class B extends class A
{
#override
public boolean method 1
{
// override same method as above.
}
}
class Test_A
{
private static B b; // reference object of the class B
#Before
public void init()
{
b = new B ();
}
#Test
public void Test_method 1
{
b.method 1; // use some assertion statements.
}
}
If an abstract class is appropriate for your implementation, test (as suggested above) a derived concrete class. Your assumptions are correct.
To avoid future confusion, be aware that this concrete test class is not a mock, but a fake.
In strict terms, a mock is defined by the following characteristics:
A mock is used in place of each and every dependency of the subject class being tested.
A mock is a pseudo-implementation of an interface (you may recall that as a general rule, dependencies should be declared as interfaces; testability is one primary reason for this)
Behaviors of the mock's interface members -- whether methods or properties
-- are supplied at test-time (again, by use of a mocking framework). This way, you avoid coupling of the implementation being tested with the implementation of its dependencies (which should all have their own discrete tests).
Following #patrick-desjardins answer, I implemented abstract and it's implementation class along with #Test as follows:
Abstract class - ABC.java
import java.util.ArrayList;
import java.util.List;
public abstract class ABC {
abstract String sayHello();
public List<String> getList() {
final List<String> defaultList = new ArrayList<>();
defaultList.add("abstract class");
return defaultList;
}
}
As Abstract classes cannot be instantiated, but they can be subclassed, concrete class DEF.java, is as follows:
public class DEF extends ABC {
#Override
public String sayHello() {
return "Hello!";
}
}
#Test class to test both abstract as well as non-abstract method:
import org.junit.Before;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.contains;
import java.util.Collection;
import java.util.List;
import static org.hamcrest.Matchers.equalTo;
import org.junit.Test;
public class DEFTest {
private DEF def;
#Before
public void setup() {
def = new DEF();
}
#Test
public void add(){
String result = def.sayHello();
assertThat(result, is(equalTo("Hello!")));
}
#Test
public void getList(){
List<String> result = def.getList();
assertThat((Collection<String>) result, is(not(empty())));
assertThat(result, contains("abstract class"));
}
}