Testing concrete methods in abstract classes using subclasses - java

abstract class BaseClass{
private final Dependency dep;
BaseClass(final Dependency dep){
this.dep = dep;
}
abstract void toBeImplementedBySubclasses();
public int concreteMethod(){
//Do some processing
return any_integer;
}
}
class DerivedOne{
#Inject
DerivedOne(final Dependency dep){
super(dep);
}
public void toBeImplementedBySubclasses(){
//DO SOMETHING RELEVANT TO DERIVED ONE IMPLEMENTATION
}
}
class DerivedTwo{
#Inject
DerivedOne(final Dependency dep){
super(dep);
}
public void toBeImplementedBySubclasses(){
//DO SOMETHING RELEVANT TO DERIVED TWO IMPLEMENTATION
}
}
I want to test concrete methods in abstract class.
Is it ok if I test the concrete methods in base class in the unit test for any of the two derived classes, or is there any other way?
So, if write test for DerivedOne class, it will include test for all methods AND the concrete method of the base class as well.
I know there is a thing "Mockito.CALLS_REAL_METHODS", using which we can test abstract classes, but in my case my base class has some dependencies which I initalise/inject using super() insider constructor of my derived classes, so I cant be doing it using CALLS_REALS_METHODS

There are two options which immediately come to mind here.
Firstly, you could write an abstract test class, which handles testing these methods, and then the test classes for your concrete implementations do the rest. For example:
public abstract class YourAbstractClassTest {
protected abstract YourAbstractClass getInstance();
#Test
public void testThing() {
final YourAbstractClass instance = this.getInstance();
instance.callMethod();
Assertions.assertTrue(instance.someProperties());
}
}
Alongside:
public class ConcreteSubclassTest extends YourAbstractClassTest {
private final ConcreteSubclass instance = new ConcreteSubclass();
#Override
protected YourAbstractClass getInstance() {
return this.instance;
}
#Test
public void moreTesting() {
this.instance.implementationSpecificMethod();
}
}
You could also create a dummy subclass in a test class for it:
public class AbstractClassTest {
private final AbstractClass instance = new AbstractClass() {
#Override
public void abstractMethod() {
throw new UnsupportedOperationException();
}
}
#Test
public void testThing() {
this.instance.concreteMethod();
// Just make sure this doesn't ever go near the
// methods you dummied up above...
}
}

Related

Accessing private field of interface inside abstract test class

I have an abstract base test class and an interface. Inside the test class, a private field of type interface is declared.
abstract class FibonacciTest {
*private FibonacciImplementation fibonacciImplementation;*
public FibonacciImplementation getImplementation(){
return this.fibonacciImplementation;
}
protected void setImplementation(FibonacciImplementation fibimplem){
this.fibonacciImplementation = fibimplem;
}
abstract void createFibonacciImplementation();
#BeforeEach
void createImplementation(){
createFibonacciImplementation();
}
#Test
void invalidPosition(){
assertEquals(new BigInteger("-2"),
fibonacciImplementation.calculateFib(-2));
}
The interface is:
public interface FibonacciImplementation {
BigInteger calculateFib(int position);
}
The sub test classes for the base test class is something like this:
public class RecursiveFibonacciTest extends FibonacciTest{
#BeforeEach
void createFibonacciImplementation(){
fibonacciImplementation = new RecursiveFibonacciImplementation();* error is here
}
}
The recursivefibonacciImplentation is this:
public class RecursiveFibonacciImplementation implements FibonacciImplementation {
#Override
public BigInteger calculateFib(int position) {
if(position < 0 )
return new BigInteger("" + position);
if(position == 1 || position == 0)
return new BigInteger("1");
return calculateFib(position-1).add(calculateFib(position-2));
}
}
The problem I have is that when in the sub test class, the compiler complains that i am trying to access a private field. The private FibonacciImplementation fibonacciImplementation; field. How do i remove that error. How do I access fibonacciImplementation? The getter and setter does not seem to work.The compiler says fibonacciImplementation has private access in FibonacciTest.
Mind you, the requirement is that it has to be a private field.
Do you really need a field at all? If instances of the implementing classes are not expensive to create, you can just get an instance only when you need it, no need to store it in a field.
abstract class FibonacciTest {
abstract FibonacciImplementation createFibonacciImplementation();
#Test
void invalidPosition(){
assertEquals(new BigInteger("-2"),
createFibonacciImplementation().calculateFib(-2));
}
}
public class RecursiveFibonacciTest extends FibonacciTest{
#Override
FibonacciImplementation createFibonacciImplementation(){
return new RecursiveFibonacciImplementation();
}
}
private means it can only be accessed from within the same class. If you want a field only to be accessible by sub-classes, you'll want to mark it as protected.
Change this:
private FibonacciImplementation fibonacciImplementation;
To this:
protected FibonacciImplementation fibonacciImplementation;
In the FibonacciTest class.

How to Mock or Stub a protected method from abstract parent while testing a public method in child with both in different packages

I have legacy code that I can't change but I need to cover with a JUnit test. I've been trying out various Mockito and PowerMockito usages to no avail.
Abstract Parent
package com.parent;
public abstract class Parent {
public Parent() {
}
protected void badMethod() {
//code
}
// public methods
}
Public Child
package com.child;
public class Child extends Parent {
public void methodToTest() {
//code
badMethod();
//code
}
}
The code that I need to test comes after the call to badMethod(). Is there a way to stub, mock, or bypass the badMethod() call? There isn't an #Override for badMethod() in the child class.
The badMethod() call attempts to establish a database connection, as well as making calls to other services. I don't need any of this for the code that I am actually testing.
You can extend the class Child in your test and "disable" the badMethod in the new class.
public class YourTest {
#Test
public void testSomething() {
Child child = new ChildWithDisabledBadMethod();
child.methodToTest();
//put your assertions here
}
private static class ChildWithDisabledBadMethod extends Child {
protected void badMethod() {
}
}
}

calling non abstract method in abstract class java

I have 3 classes. It seems basic question. But I can'nt find answer by googling.
public abstract class Test {
void t1()
{
System.out.println("super");
}
}
public class concret extends Test{
void t1()
{
System.out.println("child");
}
void t2()
{
System.out.println("child2");
}
}
public class run {
public static void main(String[] args) {
Test t=new concret();
t.t1();
}
}
How do I call abstract class t1 method? Since I cant create object from abstract class how do I call t1 in abstract class?
Thank you.
Either you create a concrete class which doesn't override the method, or within a concrete class which does override the method, you can call super.t1(). For example:
void t1()
{
super.t1(); // First call the superclass implementation
System.out.println("child");
}
If you've only got an instance of an object which overrides a method, you cannot call the original method from "outside" the class, because that would break encapsulation... the purpose of overriding is to replace the behaviour of the original method.
you should be able to do it using
Test test = new Test(){};
test.t1();
Abstract class means the class has the abstract modifier before the class keyword. This means you can declare abstract methods, which are only implemented in the concrete classes.
For example :
public abstract class Test {
public abstract void foo();
}
public class Concrete extends Test {
public void foo() {
System.out.println("hey");
}
}
See following tests:
public abstract class BaseClass {
public void doStuff() {
System.out.println("Called BaseClass Do Stuff");
}
public abstract void doAbstractStuff();
}
public class ConcreteClassOne extends BaseClass{
#Override
public void doAbstractStuff() {
System.out.println("Called ConcreteClassOne Do Stuff");
}
}
public class ConcreteClassTwo extends BaseClass{
#Override
public void doStuff() {
System.out.println("Overriding BaseClass Do Stuff");
}
#Override
public void doAbstractStuff() {
System.out.println("Called ConcreteClassTwo Do Stuff");
}
}
public class ConcreteClassThree extends BaseClass{
#Override
public void doStuff() {
super.doStuff();
System.out.println("-Overriding BaseClass Do Stuff");
}
#Override
public void doAbstractStuff() {
System.out.println("Called ConcreteClassThree Do Stuff");
}
}
public class Test {
public static void main(String[] args) {
BaseClass a = new ConcreteClassOne();
a.doStuff(); //Called BaseClass Do Stuff
a.doAbstractStuff(); //Called ConcreteClassOne Do Stuff
BaseClass b = new ConcreteClassTwo();
b.doStuff(); //Overriding BaseClass Do Stuff
b.doAbstractStuff(); //Called ConcreteClassTwo Do Stuff
BaseClass c = new ConcreteClassThree();
c.doStuff(); //Called BaseClass Do Stuff
//-Overriding BaseClass Do Stuff
c.doAbstractStuff(); //Called ConcreteClassThree Do Stuff
}
}
use keyword 'super' to do that
void t1()
{ super.t1();
System.out.println("child");
}
Make sure you use that in the overriden method though.
Your code seems to call t1(). However this is calling the concrete t1() because the abstract t1() has been overridden by the concrete class.
If you wish to call the abstract t1 method from main code, do not override the t1() in concrete.
Or you can create a method in the concrete class for example:
public void invokeSuperT1(){
super.t1();
}
Create an anonymous Inner class,
Abstract class:
abstract class Test{
abstract void t();
public void t1(){
System.out.println("Test");
}
}
Here is how to create anonymous inner class:
Test test = new Test() {
#Override
void t() {
//you can throw exception here, if you want
}
};
Call the class via the object created for abstract class,
test.t1();
An abstract class is used when we want that every class that inherited from our abstract class should implement that abstract method, so it is must to implement method otherwise it gives the compile-time error.
void t1()
{
super.t1; // means the parent methods
System.out.println("child");
}
For example: Bird class has method sing() and there other classes that inherited from it like the sparrow, Pigeon, Duck, so these all have sing method so we make Bird class Abstract and make the sing() method abstract in it so every child of bird that implements Bird class should have a method of sing() with its on implementation.
First Create abstarct class like as shown in link: Creating Abstract Class
Create Sub-Classs like as shown in link: Sub-class extending
Creating main method for executing this as show in link: Instanciate the subclass to access
Result as shown here: Result

Mockito - Mock base implementation while testing derived class implementation of same method

I am using Mockito for some unit testing. I have the following classes:
public class Base {
public void say() {
System.out.println("Base"); // some work in the base class
}
}
public class Derived extends Base {
#Override
public void say() {
super.say(); // do the base class work
System.out.println("Derived"); // some additional work in the derived class
}
}
Now I want to test the Derived class's say() method while mocking the base say() method. I followed the suggestion here: Mockito How to mock only the call of a method of the superclass and I now have.
public class DerivedTest {
#Test
public void testSay() {
Derived obj = Mockito.spy(new Derived());
Mockito.doNothing().when((Base)obj).say();
obj.say();
// assert only "Derived" was output
}
}
But this doesn't work as it mocks both the base and the derived class implementation. I want to test just the extra logic in the derived class.
How can I do this.
Update: My solution
Since I couldn't change the base class as suggested, I modified my derived class to extract all the extra logic in a a separate method and just tested that method.
public class Derived extends Base {
#Override
public void say() {
super.say(); // do the base class work
doAdditionalWork(); // some additional work in the derived class
}
void doAdditionalWork() {
System.out.println("Derived");
}
}
public class DerivedTest {
#Test
public void testDoAdditionalWork() {
Derived obj = new Derived();
obj.doAdditionalWork();
// assert only "Derived" was output
}
}
This means that I am still not testing the derived say() method but given that the logic there is quite simple now, I hope I can be excused for this. The other downside is that I can't have a visibility stricter than package-private for the doAdditionalWork() method.
When you spy an object, you completely replace the implementation of the method(s) which you've defined a mock behavior for. So, as you noted in the question, this would not work.
One trick around this is to extract an additionalBehavior() method, and test it only, without spying or mocking:
public class Base {
public void say() {
System.out.println("Base"); // some work in the base class
additionalBehavior();
}
protected void additionalBehavior() {
// No implementation. Alternatively - make it abstract
}
}
public class Derived extends Base {
#Override
protected void additionalBehavior() {
System.out.println("Derived"); // some additional work in the derived class
}
}
public class DerivedTest {
#Test
public void testAdditionalBehavior() {
Derived obj = new Derived();
obj.additioanlBehavior();
// assert that "Derived" was the output
}
}

extends of the class with private constructor

Suppose we have the following code:
class Test {
private Test() {
System.out.println("test");
}
}
public class One extends Test {
One() {
System.out.println("One");
}
public static void main(String args[]) {
new One();
}
}
When we create an object One, that was originally called the parent class constructor Test(). but as Test() was private - we get an error.
How much is a good example and a way out of this situation?
There is no way out. You have to create an available (protected, public or default) super constructor to be able to extend test.
This kind of notation is usually used in utility classes or singletons, where you don't want the user to create himself an instance of your class, either by extending it and instanciating the subclass, or by simply calling a constructor of your class.
When you have a class with only private constructors, you can also change the class to final because it can't be extended at all.
Another solution would be having a method in test which create instances of test and delegate every method call from One to a test instance. This way you don't have to extend test.
class Test {
private Test() {
System.out.println("test");
}
public static Test getInstance(){
return new Test();
}
public void methodA(){
//Some kind of implementation
}
}
public class One {
private final Test test;
One() {
System.out.println("One");
test = Test.getInstance();
}
public void methodA(){
test.methodA();
}
public static void main(String args[]) {
new One();
}
}
Make the constructor of test non-private or move One into test.
BTW, your sample code contains a few issues:
classes should be named title case (Test instead of test)
I'd suggest to make the One's constructor private unless it is called from a different class in the same package
Actually, I found there is a way out. Like this:
class Base {
private Base() {
}
public void fn() {
System.out.println("Base");
}
public static class Child extends Base {
public void fn() {
System.out.println("Child");
}
}
public static Base getChild() {
return new Child();
}
}
Now, you can use getChild() to get instance of the extended class.

Categories

Resources