mocking abstract classes [duplicate] - java

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Using Mockito to test abstract classes
I have an abstract class with functionality I need to test. I could create simple derivative of that class with no op implementations of abstract methods, but is it possible to be done with mocking framework? I need to maintain class internal state, so I can't just call
mockedInstance = mock(ClassUnderTest.class);
I need something
mockedInstance = spy(new ClassUnderTest(...));
but apparently this is impossible to do as class is abstract.

When I want to unit test an Abstract class I don't mock, I subclass.
borrowing code from mijer in other answer
public class MockitoTest {
public static abstract class MyAbstractClass {
private int state;
public abstract int abstractMethod();
public int method(....)
{
...
}
}
}
class Testclass extends MyAbstractClass
{
public int abstractMethod()
{
...
}
}
Then run your tests of MyAbstractClass using an instance of Testclass.
you can control the implementation of the abstract methods in your local subclass.

import org.junit.Test;
import org.mockito.internal.stubbing.answers.CallsRealMethods;
import static org.mockito.Mockito.*;
import static org.junit.Assert.*;
public class MockitoTest {
public static abstract class MyAbstractClass {
private int state;
public abstract int abstractMethod();
public void method() {
System.out.println("method. State: " + (++state));
System.out.println("abstractMethod: " + abstractMethod());
anotherMethod();
}
public void anotherMethod() {
System.out.println("anotherMethod. State: " + (++state));
}
}
#Test
public void test() throws Exception {
MyAbstractClass obj = mock(MyAbstractClass.class, new CallsRealMethods());
doReturn(5).when(obj).abstractMethod();
obj.method();
verify(obj).abstractMethod();
assertEquals(2, obj.state);
}
}
-EDIT-
If you need to maintain internal state of the object you have to use org.mockito.internal.util.reflection.Whitebox.setInternalState, for example:
#Test
public void test() throws Exception {
MyAbstractClass obj = mock(MyAbstractClass.class, new CallsRealMethods());
setInternalState(obj, "state", 100);
doReturn(5).when(obj).abstractMethod();
obj.method();
verify(obj).abstractMethod();
assertEquals(102, obj.state);
}
If you have an abstract class with a complex logic in its constructor which you would like to test, you should extend this class just for testing or refactor your class moving all the logic to some method to be tested.

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

Mockito calling real methods when attempting to stub methods implemented on a package private superclass

This may be the same root question as this question, but much easier to reproduce.
The issue is when stubbing interface methods on a mocked public class which extends a package private class that has the interface method implementations. Mockito will call the real interface method implementations in the package private class. See the following example.
Interface
public interface DontCallMe {
int dontCallMeSuper();
int dontCallMe();
}
Package default class which implements one of the interface methods.
abstract class PackagePrivate
implements DontCallMe {
#Override
public int dontCallMeSuper() {
throw new IllegalArgumentException("don't call me super");
}
}
Public subclass of the package private class that implements the other.
public class Public
extends PackagePrivate {
public Public() {
super();
}
#Override
public int dontCallMe() {
throw new IllegalArgumentException("don't call me");
}
}
Test class
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.junit.Test;
public class ExampleJunit {
#Test
public void testStaticConstructorInnerClass() {
final Public comparable = mock(Public.class);
when(comparable.dontCallMe()).thenReturn(1);
when(comparable.dontCallMeSuper()).thenReturn(1);
}
}
Results of running the test
java.lang.IllegalArgumentException: don't call me super
at PackagePrivate.dontCallMeSuper(PackagePrivate.java:6)
at Public.dontCallMeSuper(Public.java:1)
at ExampleJunit.testStaticConstructorInnerClass(ExampleJunit.java:19)
I can work around this by making PackagePrivate public, but that is not great. Is there any way for me to stub methods implemented on a PackagePrivate class?
You can mock the interface (DontCallMe) instead of the class (Public):
final DontCallMe comparable = mock(DontCallMe.class);
Or, if you need to mock methods that are in Public but not in DontCallMe, you can create a new interface and mock that instead.
For instance, using your original DontCallMe definition, you can do this:
public interface IPackagePrivate extends DontCallMe {
int extraMethod();
}
------
abstract class PackagePrivate implements IPackagePrivate {
public int dontCallMeSuper() {
throw new IllegalArgumentException("don't call me super");
}
}
------
public class Public extends PackagePrivate {
public Public() {
super();
}
public int dontCallMe() {
throw new IllegalArgumentException("don't call me");
}
public int extraMethod() {
throw new IllegalArgumentException("extra method");
}
}
------
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.junit.Test;
public class ExampleJunit {
#Test
public void testStaticConstructorInnerClass() {
final IPackagePrivate comparable = mock(IPackagePrivate.class);
when(comparable.dontCallMe()).thenReturn(1);
when(comparable.dontCallMeSuper()).thenReturn(1);
when(comparable.extraMethod()).thenReturn(1);
}
}
Doing some more googling, this is a known mockito bug. See https://github.com/mockito/mockito/issues/168. Fix proposed in https://github.com/mockito/mockito/pull/171 targeted for mockito 2.0

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

JUnitTest failing when creating subclass object

I got this superclass where I have some methods, one method is:
abstract public void setHP(int health);
In my subclass I have this method
public void setHP(int health){ super.health = health }
I then wrote a JUnitTest:
#Test
public void testEliteHetestUalth()
{
Subclass unit = new Subclass();
...
}
And here it just fails, it's like I cant create an object of the subclass. Is there anything special about creating objects for subclasses? I hope I gave enough information.
For me, everything works fine:
I have superclass:
package tests;
public class Superclass {
int health;
}
subclass:
package tests;
public class Subclass extends Superclass {
public void setHP(int health){
super.health = health;
}
}
and test:
package tests;
import org.junit.Test;
public class MyJUnit {
#Test
public void testEliteHetestUalth() {
Subclass unit = new Subclass();
}
}

How can you access public methods from private class from a different class in java?

I just have a question, is there any way to access public methods from a class which is private from a different class? For Example the print method can be accessed from a different class since the class is private?
private class TestClass {
public void print() {
}
}
Yes there is.
You don't actually return an direct reference to your private class, since other classes can't use it. Instead, you extend some public class, and return your private class as an instance of that public class. Then any methods it inherited can be called.
public interface Printable {
void print();
}
public class Test {
public Printable getPrintable() {
return new PrintTest();
}
private class PrintTest implements Printable {
public void print() {
}
}
}
Test test = new Test();
test.getPrintable().print();
You can do that by extending that class with a public class. Or you can always use reflection!

Categories

Resources