I am using Powermock to unit test a class.
The Class has a queue of List of objects as private member.
I am using PowerMock createPartialMock to partially mock two of the methods (say A and B) and then explicitly calling method C and then verify.
Class Sample {
Queue<List> q;
public C() {
A();
B();
q.add(List);
}
private A() {}
private B() {}
}
Class Test {
void testSomeMethod() {
Sample mock = PowerMock.createPartialMock(Sample.class, "A", "B");
PowerMock.expectPrivate(Sample.class, A).thenReturn("true");
PowerMock.expectPrivate(Sample.class, B).thenReturn("true");
mock.C();
PowerMock.verify(mock);
}
}
Now when I run the tests, PowerMock throws exception at q.add(List); line.
Can anyone please point out what mistake am I making?
Do I have expect q.add() method call as well?
You should somehow assign a value to q attribute of Sample class.
This can be done on constructor, by a setter method or by reflection (Whitebox class or pure Java reflection code).
If you need to check whether a item is added to q, create a mock of Queue interface.
Related
I'm using Mockito with Junit version : 4.8.2
I'm not able to mock methods which expects any interface objects.
For example,
public interface If extends Xyz {
}
Class Abc {
protected List <String> getIPAddress(If x, String n) {
}
}
This is sample test method:
#Test
public void testGetIPAddress() {
Abc mockAbc = mock(Abc.class, CALLS_REAL_METHODS);
when(mockAbc.getIPAddress(any(Xyz.class), anyString())).thenReturn(new List <String>());
}
When I run the above method, I get:
NullPointerException
UPDATES
Actually I found out that the problem is using "CALLS_REAL_METHODS", when instantiating mocked object. Even if I use
when(mockAbc.getIPAddress(any(If.class), anyString())).thenReturn(null);
It is throwing NPE. The reason might be it's still calling the real method.
How do I override calling the real method in this case?
you need to call getIpAdress with an If not an Xyz
Also, new List <String>() won't work, as List is an interface, use new ArrayList<String>() instead:
#Test
public void testGetIPAddress() {
Abc mockAbc = mock(Abc.class, CALLS_REAL_METHODS);
when(mockAbc.getIPAddress(any(If.class), anyString())).thenReturn(new ArrayList<String>());
}
Let's say I have a class like this:
//this is src/a/b
package a.b;
class C
{
protected Api getApi();
}
and test like this:
//and this is test/a/d
package a.d;
class TestE {
#Test
public void test()
{
C mockedC = spy(new C());
doReturn(*somemockedapi*).when(mockedC).getApi(); // this one doesn't work!
.....
}
}
It will work if class in tests is in tests/a/b, but this is not a solution because we need access to some stuff from src/a/d. And obviously this function is accessible via inheritance, so is there any way to let mockito mock it in such case?
This is potentially quite dangerous, but can be done.
//reflectively get the method in question
Method myMethod = mockedC.getClass().getDeclaredMethod("getApi");
//manually tell java that the method is accessible
myMethod.setAccessible(true);
//call the method
myMethod.invoke(myClass, null);
//PLEASE SET THE FIELD BACK TO BE UNACCESSIBLE
myMethod.setAccessible(false);
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.
I'm new to Mockito, and think it rocks for mocking. I've just come across a case where it doesn't seem like i'm able to get it to work - that being, replacing a method of a normal object with a mock method, without the method getting called when I try to mock it.
Here's a super simplified example of what I'm trying to do, that sadly, doesn't duplicate the error, but seems to be exactly the same as my real code.
public class SimpleTest
{
public class A
{
}
public class B
{
public int getResult(A anObj)
{
throw new RuntimeException("big problem");
}
}
#Test
public void testEz()
{
B b = new B();
B spy = spy(b);
// Here are both of my attempts at mocking the "getResult" method. Both
// fail, and throw the exception automatically.
// Attempt 1: Fails with exception
//when(spy.getResult((A)anyObject())).thenReturn(10);
// Attempt 2: In my real code, fails with exception from getResult method
// when doReturn is called. In this simplified example code, it doesn't ;-(
doReturn(10).when(spy).getResult(null);
int r = spy.getResult(null);
assert(r == 10);
}
}
So currently when I run my test, the test fails by throwing an exception when I try and mock the "getResult" method of the spy. The exception is an exception from my own code (ie a runtime exception), and it happens when I try and mock the "getResult" method = ie when executing the "doReturn" line above.
Note that my real use case is more complex of course... the "B" class has lots of other methods that I want to leave as is, and just mock the one method.
So my question is how can I mock it so the method isn't called?
MAJOR NOTE: I just rewrote the entire test from scratch and it works fine now. I'm sure I had a bug in their somewhere, but it's not there now - the method isn't called when it's mocked using the spy! and for what it's worth, I'm using the doReturn syntax in mocking the method.
doReturn(10).when(spy).getResult(null);
Your reedited question works just fine now.
This commented line is wrong
when(spy.getResult((A)anyObject())).thenReturn(10);
Should be
when(spy.getResult(any(A.class))).thenReturn(10);
Full test (method isn't called)
public class SimpleTest {
public class A {
}
public class B {
public int getResult(A anObj) {
throw new RuntimeException("big problem");
}
}
#Test
public void testEz() throws Exception {
B b = new B();
B spy = spy(b);
doReturn(10).when(spy).getResult(null);
int r = spy.getResult(null);
assert (r == 10);
}
}
Result
Tests Passed: 1 passed in 0,176 s
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.