I have an abstract class, say AbstractClass where I've got a public void method myMethod without an implementation. While I'm testing this class, I've created an anonymous subclass, where I can implement myMethod as I see fit.
In AbstractClass There's another method, say myImplementedMethod which calls myMethod. Is there a trick to what I can put in myMethod in the anonymous subclass, so as to be able to verify that it has been called?
Edit:
I'm using Mockito for mocking, and it is not my place to use another framework.
public abstract class AbstractClass {
public abstract void myMethod();
public void myImplementedMethod() {
myMethod();
}
public class AbstractClassTest {
#Before
public void setUp() {
AbstractClass myClass = new AbstractClass() {
#Override
public void myMethod(){
//What could I put here?
}
}
}
#Test
public void testMyImplementedMethod() {
myClass.myImplementedMethod();
//check that myMethod is called.
}
}
If Mockito's spy works for you, great. However I don't believe it will capture internal method calls. How about the below...
public class AbstractClassTest {
boolean methodCalled = false;
#Before
public void setUp() {
methodCalled = false;
AbstractClass myClass = new AbstractClass() {
#Override
public void myMethod(){
methodCalled = true;
}
}
}
#Test
public void testMyImplementedMethod() {
assertFalse(methodCalled);
myClass.myImplementedMethod();
assertTrue(methodCalled);
}
}
You could create a spy object on your descendant class, call the implemented method and later ensure the not implemented one was called with verify
AbstractClass myInstance= Mockito.spy(myClass);
myInstance.myImplementedMethod();
Mockito.verify(myInstance).myMethod();
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
public class AbstractClassTest {
private AbstractClass myClass;
#Before
public void setUp() {
AbstractClass instance = new AbstractClass() {
#Override
public void myMethod(){}
}
myClass = spy(instance);
}
#Test
public void testMyImplementedMethod() {
myClass.myImplementedMethod();
verify(myClass).myMethod();
}
}
can't you use the reflection api like this
YourClass.getClass().getMethod("myMethod").invoke(obj,args); // pass the appropriate parameters
and if this throws an exception then you havent implemented the method.
I didnt try this myself , if it works do comment .
Related
I'm trying to build a base class with a method that needs to call a private method before and after performing the actual logic.
public abstract class Base {
public Base() {}
private void before() {
// doSomething
}
private void after() {
// doSomething
}
public void actual(Object object) {
before();
// doSomething
after();
}
}
public class SomeClass extends Base {
public SomeClass() {}
public void actual(Object object) {
// actual code that needs to be executed between before and after methods.
}
}
How would I go about this?
Create another method that can be overridden and implemented instead of overriding actual directly.
E.g.
public void actual(Object object) {
before();
doActual(object);
after();
}
protected abstract void doActual(Object object);
You could make the actual() method final if you want to ensure that nobody overrides it by mistake.
You can make the method as abstract e.g.
protected abstract void actual(Object object);
and create another public method which is going to be called
public void init(Object object){
before();
actual(object);
after();
}
In java, I'd like to do something like this
public class Tata{
public static void f(){
//something
}
public static void g(){
//something
}
}
public class Titi{
public static void f(){
//something
}
public static void g(){
//something
}
}
public class Toto{
private Class c = Tata.class; //or Titi.class
public static void main(String[] args) {
c.f();
c.g();
}
}
To be precise, I'd like to be able to freely switch between classes Tata and Titi, to use their respective methods f or g.
This doesn't work as intended, as I get the cannot resolve method 'f()' error. Simply replacing c.f(); and c.g(); with Tata.f(); and Tata.g(); works fine, but defeats the purpose of using a parameter. How to solve this?
Will turn the comment into answer after all.. The correct (Java) way to deal with what you want is the use of interface. So in your demo code the implementation would be the following:
public interface TheFGFunctions {
void f();
void g();
}
public class Tata implements TheFGFunctions {
#Override
public void f() {
//something
}
#Override
public void g() {
//something
}
}
public class Titi implements TheFGFunctions {
#Override
public void f() {
//something
}
#Override
public void g() {
//something
}
}
public class Toto {
private TheFGFunctions c;
public Toto(TheFGFunctions c) {
this.c = c;
}
public void notStaticFunction() {
c.f();
c.g();
}
}
This way is totally typesafe with zero exceptions to deal with!
You cannot access a static method polymorphically. The Java language doesn't support it.
The reason your current approach fails is that c is an instance of the class Class, and the class Class doesn't define methods f() or g().
(The methods that it does define are listed in the javadoc for Class. Note that Class is final so you can't create a custom subclass with extra methods.)
The simple alternative is to use reflection; e.g.
Class c =
Method f = c.getMethod("f");
f.invoke(null); // because it is static
But note:
This is not statically type-safe. The compiler cannot tell when you make the mistake of trying to use a static f() on a class that doesn't have such a method.
There are a few exceptions that you need to deal with; e.g. missing methods, incorrect signatures, methods that are not static, methods that don't have the correct access.
Other answers have proposed creating an interface and wrapper classes to make certain static methods dispatchable. It will work and it will be compile-time type-safe (!) but there is a lot of boiler plate code to write.
#Michael Michailidis commented:
Thus interfaces!
Yea ... kind of. You can only dispatch polymorphically on instance methods declared on an interface. That implies that you must have an instance of Tata or Titi, and call the methods on it. My reading of the Question is that the author wants to avoid that.
(IMO, the avoidance is the real problem. You are better of not trying to avoid instance methods.)
FWIW, you can declare static methods in an interface (since Java 8), but they would behave the same as if you declared them in a class. You wouldn't be able to dispatch ...
You could use reflections:
private Class c = Tata.class;
public Toto() throws Exception {
c.getMethod("f").invoke(null);
c.getMethod("g").invoke(null);
}
Here my Tata class
public class Tata {
public static void f() {
System.out.println("ffff");
}
public static void g() {
System.out.println("gggg");
}
}
Output on new Toto() call:
ffff
gggg
Update (call with parameters):
public Toto() throws Exception {
c.getMethod("f", String.class).invoke(null, "paramValue1");
c.getMethod("g", String.class).invoke(null, "paramValue2");
}
public class Tata {
public static void f(String param1) {
System.out.println("ffff " + param1);
}
public static void g(String param2) {
System.out.println("gggg " + param2);
}
}
Output:
ffff paramValue1
gggg paramValue2
Write a wrapper interface
interface CWrapper {
void f();
void g();
}
and wrapper class factory method for each Class containing the methods
class CWrappers {
CWrapper forTiti(Class<Titi> titiClass) {
return new CWrapper() {
void f() { Titi.f(); }
void g() { Titi.g(); }
}
}
// another factory method for Tata
}
Then you can use that:
public class Toto {
private CWrapper c = CWrappers.forTata(Tata.class); //or forTiti(Titi.class)
public static void main(String[] args) {
c.f();
c.g();
}
}
I'm looking for a way in JMockit to inject the private fields inside a class while maintaining the ability to trigger the real methods. I use #Injectable and #Tested offered by JMockit. But somehow after that the injected instance is not able to call the real method.
Example test:
public class TestClass {
public static class DoSomething {
private Call callee;
public void execute() {
callee.call();
}
}
public static class Call {
public void call() {
System.out.println("real");
}
}
#Tested DoSomething doSomething;
#Injectable Call call;
// nothing happens
#Test
public void testRealCall() {
doSomething.execute();
}
// invocation doesn't help either
#Test
public void testRealCallSecondTry() {
new MockUp<Call>() {
#Mock
#SuppressWarnings("unused")
public void call(Invocation inv) {
inv.proceed();
}
};
doSomething.execute();
}
// this works, but requires redundant methods
#Test
public void testRealCallThirdTry() {
new MockUp<Call>() {
#Mock
#SuppressWarnings("unused")
public void call() {
System.out.println("real");
}
};
doSomething.execute();
}
#Test
public void testFakeCall() {
new MockUp<Call>() {
#Mock
#SuppressWarnings("unused")
public void call() {
System.out.println("fake");
}
};
doSomething.execute();
}
}
Here DoSomething wraps the Call instance, which provides a way to print a message. The ideal output of the four test cases would be:
real
real
real
fake
However the actual scenario is that only 3 and 4 worked, printing:
real
fake
This shows if an instance is created using #Injectable. It's not able to directly call the original method without copying and pasting the old method body to the mocked version. That seems really awkward. Is there a workaround of this?
My understanding is that if you use #Injectable you just get an empty mock and then you can no longer call the original method.
The workaround that I would use is to do the injection "manually" like this:
public class TestClass {
public static class DoSomething {
private Call callee;
public void execute() {
callee.call();
}
}
public static class Call {
public void call() {
System.out.println("real");
}
}
#Tested DoSomething doSomething;
//#Injectable Call call;
// nothing happens
#Test
public void testRealCall() {
Deencapsulation.setField(doSomething, "callee", new Call());
doSomething.execute();
}
// invocation doesn't help either
#Test
public void testRealCallSecondTry() {
new MockUp<Call>() {
#Mock
#SuppressWarnings("unused")
public void call(Invocation inv) {
inv.proceed();
}
};
Deencapsulation.setField(doSomething, "callee", new Call());
doSomething.execute();
}
// this works, but requires redundant methods
#Test
public void testRealCallThirdTry() {
new MockUp<Call>() {
#Mock
#SuppressWarnings("unused")
public void call() {
System.out.println("real");
}
};
Deencapsulation.setField(doSomething, "callee", new Call());
doSomething.execute();
}
#Test
public void testFakeCall() {
new MockUp<Call>() {
#Mock
#SuppressWarnings("unused")
public void call() {
System.out.println("fake");
}
};
Deencapsulation.setField(doSomething, "callee", new Call());
doSomething.execute();
}
}
I ran into this question when I had the same problem. However, the existing answer don't work with newer versions of JMockit.
If a field in the tested class is annotated with #Inject, a corresponding #Injectable is required in the test class. Usually. This means that removing the #Injectable and instead mock the class with MockUp suggested in the other answer doesn't work. JMockit will complain with "Missing #Injectable for field ...".
What needs to be done instead is to change the #Injectable annotation to a #Tested annotation, i.e. change this
#Injectable Call call;
to
#Tested Call call;
call becomes a real instance and JMockit doesn't complain about a missing #Injectable. If you need to mock some methods in call, it can be done with MockUp as usual.
new MockUp<Call>() {
#Mock
public void someMethodToMock() {
}
};
Assuming three classes, one being a subclass of the other. Each overwrite the parents' method.
public class BaseClass {
public void doStuff() {
performBaseTasks();
}
}
public class MiddleClass extends BaseClass {
// {BaseClass} Overrides
public void doStuff() {
performMiddleTasks();
super.doStuff();
}
}
public class FinalClass extends MiddleClass {
// {BaseClass} Overrides
public void doStuff() {
performFinalTasks();
super.doStuff();
}
}
When calling new FinalClass().doStuff(), this would lead to a method
invokation order as follows:
performFinalTasks();
performMiddleTasks();
performBaseTasks();
I want to bring the perfomFinalTasks() between performMiddleTasks() and
performBaseTasks(). How can I do this?
performMiddleTasks();
performFinalTasks();
performBaseTasks();
Write a public method in final class doStuffDifferently() and invoke these methods in that order. I am not sure it's possible to do it via any other tricks in the doStuff() method.
One possible way, if you can make the middle class abstract:
public abstract class MiddleClass extends BaseClass {
// {BaseClass} Overrides
public void doStuff() {
performMiddleTasks();
doProxyExec();
super.doStuff();
}
public abstract void doProxyExec();
}
You override the proxy method in your subclass:
public class FinalClass extends MiddleClass {
// {BaseClass} Overrides
public void doStuff() {
super.doStuff();
}
// {MiddleClass} Overrides
public void doProxyExec(
performFinalTasks();
}
}
A not very polymorphic way of method call chaining, but then again the original design is kind of ... odd.
http://stackoverflow.com/questions/6645263/unit-testing-overridden-methods-which-call-super (This question has similar wording but is not the same)
I have something along the lines of:
public class SuperClass {
private int superClassInteger = 2;
public void superClassMethod() {
superClassInteger = 5;
}
public int getSuperClassInteger() {
return superClassInteger();
}
}
Then in my test I have:
public class SuperClassTest {
public void testSuperClassMethod() {
SuperClass superClass = new SuperClass();
superClass.superClassMethod();
assertEquals(5, super.getSuperClassInteger())
}
}
I then have a subclass:
public class SubClass {
private int subClassInteger = 2;
public void subClassMethod() {
super.superClassMethod();
subClassInteger = 32;
}
public int getSuperClassInteger() {
subClassInteger;
}
}
Then my test for the subclass:
public class SubClassTest {
public void testSubClassMethod() {
SubClass subClass = new SubClass();
subClass.subClassMethod();
assertEquals(5, subclass.getSuperClassInteger());
assertEquals(32, subclass.getSubClassInteger())
}
}
My problem is that to test the behavior of the subclass, I am repeating the test code I have for the super class. I could take out: assertEquals(5, subclass.getSuperClassInteger()); as I just want to test the business logic of the subclass. However, the problem with this is that if somebody accidentally removes the call to superClassMethod the test will still pass. So I need verify that a call to super is made. What is a common way of testing this use case?
Note: I know composition / strategy pattern vs inheritance helps solve this problem but for that to be the solution you are basically saying that I should NEVER override a method and invoke super in my code (which I find hard to believe there will never be a use for)
Use mockito spies. You can check for nearly any method call using that testing Framework.
https://github.com/mockito/mockito
This is probably not the answer you want (i.e not a workaround), but the answer you deserve but you should never override a method and invoke super.
I'm working on a legacy project that does that a lot, it's a nightmare to maintain, to debug and to test.
Instead, it's better to use an abstract class with a template method pattern:
Before
public class SuperClass<T> {
public void include(T t) {
validate(T);
dao.save(T);
}
// I've found code like that.
public void validate(T t) {
}
}
public class SubClass1 extends SuperClass<MyClass> {
#Override
public void include(MyClass mc) {
doStuff(mc);
doMoreStuff(mc);
super.include(mc);
}
#Override
public void validate(MyClass mc) {
doValidationStuff();
}
}
public class SubClass2 extends SuperClass<AnotherClass> {
#Override
public void include(AnotherClass ac) {
doDifferentStuff();
super.include(mc);
}
}
After
public abstract class AbstractClass<T> {
abstract void validate(T t);
// this method can now be tested
public void include(T t) {
validate(T);
dao.save(T);
}
}
public class Class1 extends AbstractClass<MyClass> {
public void validate(MyClass mc) {
doValidationStuff();
doStuff(mc);
doMoreStuff(mc);
}
}
public class Class2 extends AbstractClass<AnotherClass> {
public void validate(AnotherClass ac) {
doDifferentStuff();
}
}
As you can see, this refactoring simplifies maintenance and testing, you don't have to worry about having to mock the superclass method call in the Class1 and Class2 tests, and the code is closed to modification and open to extension, i.e, more maintainable.
Use JMockit and check the call to super with a Verification.
JMockit
Example for this
public void test {
SubClass subClass = new SubClass();
subClass.subClassMethod();
new Verifications() {
// mock only this method of superClass - and only in this test
#Mocked (methods = "superClassMethod")
SuperClass superClass;
{
superClass.superClassMethod();
times = 1; // specify invocation count
}
};
}