Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test protected methods of abstract class using JUnit and JMock

I have such situation - I have interface (say MyInterface) and simple partial implementation (AbstractMyInterface). The latter adds a few protected methods which I would like to test.

Currently I simply write by hand a mock object which extends AbstractMyInterface and export protected methods as public. Is there a simpler way of doing this - for example using JMock+scripting?

like image 783
Maciej Piechotka Avatar asked Dec 04 '11 13:12

Maciej Piechotka


People also ask

How do you test protected methods in JUnit?

To test a protected method using junit and mockito, in the test class (the class used to test the method), create a “child class” that extends the protagonist class and merely overrides the protagonist method to make it public so as to give access to the method to the test class, and then write tests against this child ...

Can you test a protected method?

In most languages, you can make a method protected (instead of public), and put the test class in the same package (or whatever), and the method will be available for test.

Can we write JUnit test cases for abstract class?

With JUnit, you can write a test class for any source class in your Java project. Even abstract classes, which, as you know, can't be instantiated, but may have constructors for the benefit of “concrete” subclasses.


2 Answers

I cannot see any problem with testing protected methods with JUnit. As long as package structure for tests mirrors source tree structure, methods other than private are visible for tests.

Of course if implementation to test is abstract, you have to create normal subclass of class under test by yourself (or do it via some mocking library if fits better for your purposes). Also in such a case, no need to create layer of public methods for just for calling protected visibility methods. Only for private methods this strategy does not work. But often need to test private methods is sign of design problem anyway.

For example: Class to test located to src/mypackage/AbstractClass.java package mypackage;

/** This could as well implement some interface, 
    but that does not change a thing */
public abstract class AbstractClass {
    protected int returnsOne() {
        return 1;
    }
}

And test which is located to tests/mypackage/AbstractClassTest.java

package mypackage;

import org.junit.Test;

import static junit.framework.Assert.assertEquals;

public class AbstractClassTest {
    @Test
    public void returnsOneReturnsOne() {
        AbstractClass instanceToTest = new AbstractClassTestable();
        assertEquals(1, instanceToTest.returnsOne());
    }
}

/** This is needed, because we cannot construct abstract class directly */
class AbstractClassTestable extends AbstractClass {
}
like image 89
Mikko Maunu Avatar answered Oct 05 '22 12:10

Mikko Maunu


Just a suggestion,

What if we don't test the protected methods, can we use the public methods to cover those protected methods?

If not, is it because of the protected methods too complicated, refactor to extract the complicated things to a new object, which provides public interfaces, leaving the old object just one private object in some public methods.

The test will later be on the new object.

This blog post might be helpful.

like image 26
Chris Zheng Avatar answered Oct 05 '22 11:10

Chris Zheng