I'm wondering if there is a way to specify that a method gets called in advance of a class method. I know something like this should be posssible, since JUnit has before(), what I want to do is similar.
Here is a concrete example of what I'd like to do
class A {
public void init(int a) {
System.out.println(a);
}
#magic(arg=1)
public void foo() {
//
}
public static void main() {
A a = new A();
a.foo();
}
}
//Output: 1
Basically I want an annotation to tell either the compiler or the jvm call init() before foo()
If you have interface A you can wrap instances of this interface with Proxy and inside invoke method of its InvocationHandler you are free to check whether method is annotated and perform some actions depending on that:
class Initalizer implements InvocationHandler {
private A delegate;
Initializer(A delegate) {
this.delegate = delegate;
}
public Object invoke(Object proxy, Method method, Object[] args) {
if (method.isAnnotationPresent(magic.class)) {
magic annotation = method.getAnnotation(magic.class);
delegate.init(magic.arg);
}
method.invoke(delegate, args);
}
}
A realA = ...;
A obj = Proxy.newProxyInstance(A.class.getClassLoader(), new Class[] {A.class}, new Initializer(realA));
Or you can try using "before" advice of AspectJ. It will be something like the next:
#Aspect
public class Initializer {
#Before("#annotation(your.package.magic) && target(obj) && #annotation(annotation)")
private void initialize(A obj, magic annotation) {
a.init(annotation.arg);
}
}
I'm not sure that snippets are working, they just illustrate idea.
Why are you doing this? Are you attempting to avoid having a constructor with many arguments (using setters then calling init) or are you avoiding having many constructors that all have similar arguments? If this is the case, you can use a builder pattern.
public class Foo {
int a, b, c, d, e;
Foo(int a, int b, int c, int d, int e) { this.a=a; /*etc*/ }
}
public class FooBuilder {
int a,b,c,d,e;
FooBuilder A(int a) { this.a=a; return this;}
FooBuilder B(int b) { this.b=b; return this;}
//etc
Foo create(){ return new Foo(a,b,c,d,e);
}
If this doesn't work, I'd suggest looking into AOP. I'd mark the methods that must have init() called already with an annotation [perhaps #requires('init') or the like] and make you AOP framework insert the proper code. Be careful that multiple init's either don't have side effects or that you do proper synchronization on your has_init_been_called state.
Just call Init() at the start of foo()?
AOP does this with what are known as pointcuts
AspectJ might have what you need.
Simplistically speaking, you would add before advice to your foo() method which would call init()
There is no direct way to do this in the java language. What you are seeing in JUnit is the framework making a decision about how to run the methods by calling the methods annotated with #Before first. It is very easy to find annotated methods and run them, but that is the responsibility of the caller.
The problem you present is too simple to know the right way to a solution. AspectJ does address this need by manipulating the byte code (essentially calling the init() method when foo() is called by changing the bytecode to make that happen), but I can't imagine introducing that as a hack around a problem.
If you can present an interface or a wrapper object to this class, you could do it that way. But I would suggest you post the ugly hack that got you into this situation in the first place in a separate question, and then post how your current hack solution requires that method calls be intercepted and why that is the case, and if there are better workarounds. That way we can help address the underlying need better.
Have a look at AspectJ. It will help you do what you are asking.
I assume that the problem here is as follows:
You have a constructor that can partially build the object, but can't completely build it because of the way the class must be constructed. (I can't think of an example offhand.)
So you need an init() method that will finish construction.
So you want to have some kind of guarantee that init() will be called right after the constructor.
My suggestion is to use a factory object or method. The simplest way is to make the constructor private, add a construct() method with the parameters of the constructor or something of that sort, and then have the construct() method both create the object and call init(), then return it.
Related
I am new to Mockito, please help in understanding the basic.
According to me above code is supposed to print 5 when mocked.add(6,7) gets called , but add() method is not getting called and the code prints 0.. why ? any solution for this code ?
import org.mockito.Mockito;
import static org.mockito.Mockito.*;
class Calc{
int add(int a,int b){
System.out.println("add method called");
return a+b;
}
}
class MockTest{
public static void main(String[] args) {
Calc mocked=mock(Calc.class);
when(mocked.add(2,3)).thenReturn(5);
System.out.println(mocked.add(6,7));
}
}
In order to get result of 5, you have to pass the exact params as when you set up the when..then. Otherwise mockito will return a 'default' value (which is 0 for integer:
What values do mocks return by default?
In order to be transparent and unobtrusive all Mockito mocks by
default return 'nice' values. For example: zeros, falseys, empty
collections or nulls. Refer to javadocs about stubbing to see exactly
what values are returned by default.
If you want to return 5 for any integer then use:
when(mocked.add(Mockito.any(Integer.class),Mockito.any(Integer.class))).thenReturn(5);
A "mock" is just an empty dummy object that simulates behaviour of a "real" object. If you define a behaviour such like when(mocked.add(2,3)).thenReturn(5); you specifically tell this mock what to do, when it receives those exact values.
mocked.add(6,7) will return 0 at that point, since you haven't defined its behaviour for those values and therefore uses a default value. So if you want to cover all possible inputs, you can go with the solution #MaciejKowalski posted and use the generic matchers like Mockito.any(Integer.class).
Still I believe it is not clear how to correctly handle mocks. Mocks are a way of providing external dependencies to a system-under-test without the need to set up a whole dependency tree. The real methods inside that class are usually not called. That's what something like when(mocked.add(2,3)).thenReturn(5); means. It tells the mock to behave like the real dependency without actually having it at hand.
An example could look like this:
public class TestClass {
private ExternalDependency dep;
public void setDep(ExternalDependency dep) {
this.dep = dep;
}
public int calculate() {
return 5 + dep.doStuff();
}
}
public class ExternalDependency {
public int doStuff() {
return 3;
}
}
Now in your test code you can use mocks like this:
#Test
public void should_use_external_dependency() {
// Aquire a mocked object of the class
ExternalDependency mockedDep = Mockito.mock(ExternalDependency.class);
// Define its behaviour
Mockito.when(mockedDep.doStuff()).thenReturn(20);
TestClass sut = new TestClass();
sut.setDep(mockedDep);
// should return 25, since we've defined the mocks behaviour to return 20
Assert.assertEquals(25, sut.calculate());
}
If sut.calculate() is invoked, the method in ExternalDependency should not be really called, it delegates to the mocked stub object instead. But if you want to call the real method of the real class, you could use a Spy instead with Mockito.spy(ExternalDependency.class) or you could do that with when(mockedDep.doStuff()).thenCallRealMethod();
I have two classes Test and Encap. I have a private variable a and access via setter and getter method. and i'm inheriting the class Test with Encap.
now i am able to change the value of a using setValue(int a). i want to restrict that option. i want it to make it as a read only value. please assist me in this.
class Test
{
private int a;
protected void setValue(int a)
{
this.a = a;
}
protected void getValue()
{
System.out.println("The assigned value of a is : "+this.a);
}
}
public class Encap extends Test {
public static void main(String [] args)
{
Test t = new Test();
t.setValue(4);
t.getValue();
Encap e = new Encap();
e.setValue(3);
e.getValue();
}
}
One option would be to delete the method setValue() from the class Test:
class Test
{
private int a;
protected void getValue()
{
System.out.println("The assigned value of a is : "+this.a);
}
}
Edit:
Why to do this? If Encap inherits from Test, it should be able to do the same actions as Test. Otherwise, what's the purpose of inheriting? If you still thinking that Test should be able to modify the value and Encap not, maybe your design is wrong. You could try something like this instead:
BaseClass
---------
+getValue
/ \
/ \
Test Encap
-------- ---------
+setValue
If you mean that you want a derived class to not expose public methods of the superclass, then your code probably 'smells'...
Remember that Inheritance models "Is A"
So in your example an Encap is a Test and you should be able to do anything to an Encap that you can do to a Test.
However, if you simply must inherit from a class where you don't want to expose a parent-class method, you can override the method and have its body do nothing. But for simple getter and setter accessor methods this is potentially very confusing for clients of your code.
If you can't reconcile things and calling setValue() on an Encap is never the right thing to do, i would recommend overriding the method, commenting it liberally and have it do nothing, or throw an exception to indicate to the client that they're doing something that doesn't make sense.
I'm using PowerMock and I'd like to know how to keep all behavior of the child class, but stub super calls that may be overriden by the child.
Say I have this class:
public class A {
public String someMethod() {
return "I don't want to see this value";
}
}
and a sub class:
public class B extends A {
#Override
public String someMethod() {
return super.someMethod() + ", but I want to see this one";
}
}
How do I stub the call to super.someMethod()?
I've tried
#Test
public void test() {
B spy = PowerMockito.spy(new B());
PowerMockito.doReturn("value").when((A)spy).someMethod();
assertEquals("value, but I want to see this one", spi.someMethod());
}
You can try suppressing the methods from the Parent class,
PowerMockito.suppress(methodsDeclaredIn(A.class));
Here's an article on Stubbing, suppressing and replacing with PowerMock that might be of some use.
https://www.jayway.com/2013/03/05/beyond-mocking-with-powermock/
Don't forget to add #PrepareForTest({ParentClassToSupress.class}) on your test class. Then you can do as Steve suggests and suppress methods in the parent: PowerMockito.suppress(methodsDeclaredIn(ParentClassToSupress.class));
The cast you're attempting is not going to work as you are expecting. However, I think you have a couple of options to get around this, certainly with PowerMockito.
Take a look at this StackOverflow answer.
I use Mockito 1.8.0 so I do not have AnyVararg. Upgrading to later version of Mockito is not on cards from my team at the moment. So please bear with me.
What the class looks like:
public abstract class Parent {
public void someMethod(String a, String b)
{
//.....
}
public void foo(String a, String... b)
{
//.....
}
}
public class Child extends Parent{
public void bar() {
someMethod(a,b);
foo(a,b,c);
methodToFailUsingSpy();
}
}
Unit tests
#Test
public void someTest() {
private spyOfChild = //initialize here;
doReturn("Something")).when(spyOfChild).methodToFailUsingSpy();
/* Tried using this, but did not help.
doCallRealMethod().when(spyOfChild).foo(anyString());
*/
spyOfChild.bar();
}
Problem -
When the spy sees someMethod(), it calls the real method in the abstract class. But when it sees foo(), it tries to find a matching stubbed method i.e control goes to Mockito's MethodInterceptorFilter, since it is not able to find a mock, it throws java.lang.reflect.InvocationTargetException.
I do not want foo() to be mocked. I want the real method to be called like it happens in someMethod(). Can someone explain if it is because of using method with variable length arguments with a spy?
This is a bug in Mockito.
https://groups.google.com/forum/#!msg/mockito/P_xO5yhoXMY/FBeS4Nf4X9AJ
Your example is quite complicated, to reproduce the problem is very simple:
class SimpleClass {
public String varargsMethod(String... in) {
return null;
}
public void testSpyVarargs() {
SimpleClass sc = Mockito.spy(new SimpleClass());
sc.varargsMethod("a", "b");
}
}
Even this will produce the error you describe, and the workaround suggested in the link doesn't work for me.
Unfortunately to get around this you will need to upgrade Mockito. Changing to version 1.9.5 makes the above run fine, plus you get the varargs matchers as you say (although note that your problem isn't to do with matchers but how Mockito handles spied varargs methods).
I don't think there were too many huge changes between 1.8.0 and 1.9.5, it shouldn't be too painful.
If I have the method public void send() { /* some code */ } in a class and have a child of this class also have a method public void send() { /* some code*/ }, how do I ensure that the child must call super.send() somewhere in the send() method that it's trying to override?
I was wondering about this because I've written in APIs where if you don't call the super of that method when overriding it, it'll throw an exception telling me that I haven't called the super method. Is this hard coded or can this be done with some keywords in Java?
You can't really, but you can...
class MySuperClass {
public final void send() {
preSend();
// do the work...
postSend();
}
protected void preSend() {
// to be overridden in by sub classes
}
protected void postSend() {
// to be overridden in by sub classes
}
}
You can do this by adding an abstract method (don't see another way) :
abstract class MyClass
{
public final void send() // forbid changing this.
{
// do something
doSend():
}
protected abstract doSend(); // no external calls
}
http://en.wikipedia.org/wiki/Call_super
What you're trying to do is an anti-pattern; you can do it (many Java core classes do), but you shouldn't - unless you have a really good reason for it.
Except for this bit, all answers provided here are correct.
Conceptually, this is like 'delegating to a child'. To achieve this, the parent class should implement final method which invoke an abstract method, which the child is supposed to implement.
abstract class Parent {
public final void invoke() {
// pre invoke code
doInvoke():
// post invoke code
}
protected abstract doInvoke(); // child should implement this
}
You can't really force a subclass to call the base one. One thing you can do is to change your send method into a base (final) "send" and a "sendcore" (virtual) which would be overriden by the subclasses. The base "send" would set some flag stating that "sendcore" hasn't been called, and then call "sendcore". When it returns it can check whether the child "sendcore" has called the base class.
There is no keyword that enforces this. In my opinion, you either
Provide the subclass with all the information (via protected methods or what not) it needs to completely override and change the send call itself, or...
Document the API so that it is known that they must eventually call send themselves via super. I would imagine most people who are overriding a superclass method would do this if enough of the class is abstracted anyway.
There's nothing built into Java to enforce calling a superclass method. One approach to this is to use private flags in the superclass together with a delegation method. Something like this:
public class Super {
private boolean inSend;
private boolean superCalled;
public final void send() {
inSend = true;
superCalled = false;
doSend();
inSend = false;
if (!superCalled) {
throw new IllegalStateException("Failed to call super.doSend()");
}
}
protected void doSend() {
if (!inSend) {
throw new IllegalStateException("Cannot call doSend() directly");
}
superCalled = true;
// base class functionality
}
}