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

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
}
}

Related

Testing concrete methods in abstract classes using subclasses

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...
}
}

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() {
}
}
}

Require Instance of Class to Override a Method

Here's the situation: I have a class and I create instances of. I'd like it to inherit the majority of the methods/variables in the class, but I want a few methods to be required to be overridden, similar to how an abstract class works.
Here is my code so far.
public class Example {
public void methodOne() {
//Inherited
}
public void methodTwo() {
//Interited
//Maybe calls methodThree() as a part of its function
}
public void methodThree() {
//Override Me
}
}
I can't [make the class abstract] because I need to create instances
Making the class abstract does prevent instantiation, but since you want to prevent instantiation unless a method is overridden, this is the right thing to do.
You can make overrides anonymously, so syntactically this would be similar to instantiating the base class:
public abstract class Example {
public void methodOne() {
//Inherited
}
public void methodTwo() {
//Interited
//Maybe calls methodThree() as a part of its function
}
public abstract void methodThree();
}
...
static void main(String[] args) {
Example e = new Example() {
#Override
public void methodThree() {
... // Do something
}
};
}
First of all, requiring people to write code in a particular way can be counter productive. Someone may have a legitimate use-case (that you had not considered !!) for dong it differently, and your restriction may force them to solve the problem in a way that makes things significantly worse than if your restriction wasn't there. Bear this in mind ...
But here's a solution:
public abstract class ExampleBase {
public void methodOne() {
// Inherited
}
public void methodTwo() {
// Interited
// Maybe calls methodThree() as a part of its function
}
public abstract void methodThree();
}
public final class Example {
#Override
public void methodThree() {
// Do stuff.
}
}
We have solved the problem by moving all of the members that you want to inherit to an abstract superclass. Any methods that you want to force people to override are declared as abstract. By declaring your concrete Example class as final, we prevent them from circumventing your requirement and subclassing Example without overriding methodThree.

How to test protected method is called or not in Mockito

This is a base class:
public abstract class BaseClass
{
protected void demoMethod()
{
//to Do
}
}
I want to test whether demoMethd() in sub class is called or not using Mockito.
I tried with Mockito.verify but call goes to sub class method but i want to super method to be called.Is there any solution to test whether super.demoMethod() is called or not. Code is given as below:
public class SubClass extends BaseClass
{
#Override
protected void demoMethod()
{
if( true)
{
return;
}
super.demoMethod();
}
}
According to me we can not call to protected method in Test class so therefore the things which i wanted is not possible for this case.

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

Categories

Resources