If you have created an Abstract Class you may want to test its non abstract methods. But there is one problem: we can’t instantiate abstract classes.
There are two ways to test their non abstract methods:
Testing Abstract Classes Through Their Children’s
Suppose we have the following abstract class named Person:
public abstract class Person {
private String firstName;
private String lastName;
public abstract void doAnything();
public String getFullName(){
return firstName + " " + lastName;
}
// Getters and setters here...
}
And a Boss class that extends Person:
public class Boss extends Person{
@Override
public void doAnything() {
System.out.println("Do anything...");
}
}
And you want to test the Person.getFullName() method. So you must create the test below:
public class PersonTest {
Person person;
@Before
public void setUp() {
person = new Boss();
person.setFirstName("Anderson");
person.setLastName("Dias");
}
@Test
public void getFullName(){
assertEquals("Anderson Dias", person.getFullName());
}
}
On this first case, it will work fine and the test will pass no matter. But there is a problem, because it’s been assumed that the Boss class will never override the getFullName() method. If the Boss class changes, the test will fail.
public class Boss extends Person {
@Override
public String getFullName(){
return "Mr. " + super.getFullName();
}
@Override
public void doAnything() {
System.out.println("Do anything...");
}
}
So, what to do? Let’s see another way to test Abstract Classes.
Creating Mock Implementations for Abstract Classes
There is a simple way to test them. You can create a mock class that simulates the implementation of an abstract class. You will guarantee that the non abstract methods will be the same of the parent abstract class.
Let’s see a sample Mock implementation:
public class MockPerson extends Person {
@Override
public void doAnything() { }
}
Notice that you don’t have to test the Person abstract class methods right now. So you don’t have to implement the doAnything() method body on the Mock implementation.
And our Test Case will be:
public class PersonTest {
Person person;
@Before
public void setUp() {
person = new MockPerson();
person.setFirstName("Anderson");
person.setLastName("Dias");
}
@Test
public void getFullName(){
assertEquals("Anderson Dias", person.getFullName());
}
}
That’s a simple way to test abstract methods.
Of course there are some specifics cases that Mock Objects don’t solve, in those cases you will need to test using the first strategy.
public abstract class Person {
private String firstName;
private String lastName;
public abstract void doAnything();
public String getFullName(){
this.doAnything();
return firstName + " " + lastName;
}
// Getters and setters here...
}
In this case our non abstract method ( Person.getFullName() ) calls the abstract method ( Person.doAnything() ), and the implementation of Person.doAnything() method may be decisive for the Person.getFullName() return. So, the only way to test it will be by the Person children classes.
I hope you enjoy it.
Thanks to Raquel Carsi for help me to write this post.
Filed under: TDD | 1 Comment
Tags: java, junit, TDD, testing, unit test
Hi! I was surfing and found your blog post… nice! I love your blog.
Cheers! Sandra. R.