JUnitTest failing when creating subclass object - java

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

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

Mock a method inside a constructor of a class

I am new to mockito. Lets say I have a class like this
public class MyClass {
int a;
String b;
public MyClass(int a) {
this.a = a;
this.b = draw();
System.out.println("class is created");
}
public String draw() {
System.out.println("my");
return "b";
}
public void apple() {
System.out.println("apple");
}
}
I am writing a JUnit test using Mockito where I am creating a object of the class by using the constructor. Is it possible to mock the draw() method when I am instating the class?
Not clear why you need the Mockito here. This is a solution without Mockito.
In your test create an instance of MyClass with overridden draw() method:
final MyClass myClass = new MyClass() {
#Override
public String draw() {
return "mock data";
}
}
// Now test your class as you want
You could turn to do partial mocking using spies (see here for how to do that).
But as usual: when people start thinking about complex ways to use mocking framework, the real answer is: step back and improve your production code. Your constructor should do only simple initialisation things.
In your case, one reasonable approach would be: don't call an internal method to compute the value of that field - but pass that value to the constructor (in other words - use dependency injection).
And you could still do something like:
public MyClass(int a) {
this(a, draw());
}
MyClass(int a, String b) {
this.a = a; ...
Now your unit tests can happily use that ctor that takes two arguments - and your need to mock anything vanishes completely.
One way to test your class with Mockito will be,
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;
public class TestMyClass {
#Mock
private MyClass clazz;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testDraw() {
when(clazz.draw()).thenReturn("My mock hello");
assertEquals("My mock hello", clazz.draw());
}
}
Complementing the solutions given, the constructor can also receive the method to mock as a function.
import java.util.function.Supplier;
public class MyClass {
int a;
String b;
public MyClass(int a, Supplier<String> draw) {
this.a = a;
this.b = draw==null? draw() : draw.get();
System.out.println("class is created");
}
public String draw() {
System.out.println("my");
return "b";
}
public void apple() {
System.out.println("apple");
}
}

Passing Object of different classes as an argument to same method

Let's say I have three Classes A,B,C.
All three do the same thing, but in a different way, they differ in efficiency.
All the method names, variable names inside the three classes are same.
class A{
public static int method(){
......
return result;
}
}
class B{
public static method(){
......
return result;
}
}
class C{
public static method(){
......
return result;
}
}
I have test class, which has a method to test the code in the above three classes. Since this testMethod() is common to all the three classes, is there a way to call this method with objects of classes A,B,C ?
class Test{
public static int testMethod(Object ABC)
{
return ABC.method();
}
public static void main(String[] args){
A a = new A();
SOP(testMethod(a));
B b = new B();
SOP(testMethod(b));
C c = new C();
SOP(testMethod(c));
}
}
The only approach I can think of is creating three different methods for each of the classes, like this.
class Test{
public static int testMethodA(A a)
{
return a.method();
}
public static int testMethodB(B b)
{
return b.method();
}
public static int testMethodC(C c)
{
return c.method();
}
public main()
{
//call to each of the three methods
............
}
What is the best approach to this scenario? Basically I want to have only one method that can test all three classes.
Create an interface with the common method for all classes. Then, make each class implement this interface. In your test code, use the interface as parameter type and pass an instance of each class to the method. Note that when you do this, the method to test should not be static.
In code:
public interface MyInterface {
//automatically public
int method();
}
public class A implements MyInterface {
#Override //important
//not static
public int method() {
/* your implementation goes here*/
return ...;
}
}
public class B implements MyInterface {
#Override //important to check method override at compile time
public int method() {
/* your implementation goes here*/
return ...;
}
}
//define any other class...
Then the test:
public class Test {
//using plain naive console app
public static void main(String[] args) {
MyInterface myInterfaceA = new A();
testMethod(myInterfaceA);
MyInterface myInterfaceB = new B();
testMethod(myInterfaceB);
//and more...
}
public static void testMethod(MyInterface myInterface) {
myInterface.method();
}
}
Or if you prefer to use JUnit:
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
public class MyInterfaceTest {
MyInterface myInterface;
#Test
public void methodUsingAImplementation() {
myInterface = new A();
//code more human-readable and easier to check where the code fails
assertThat(myInterface.method(), equalTo(<expectedValue>));
}
//similar test cases for other implementations
}

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

mocking abstract classes [duplicate]

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.

Categories

Resources