How to mock the second object in the same method? - java

Now I have a method to test using Mockito . However the method is kind of complicated. In the same method ,I need to new two objects both are the same type.
Timestamp beginTimestamp = new Timestamp(Long.parseLong(beginTimeLong));
Timestamp endTimestamp = new Timestamp(System.currentTimeMillis());
I want to mock the second object , endTimestamp , to throw an Exception , but I can not avoid the influence of beginTimestamp. Now my question is how to mock the second object, endTimeStamp, only ,and make it to throw out an exception when I call endTimestamp's certain method ,such as:
endTimestamp.getTime()
I tried to write my test code which is shown below ,
#Ignore
public void getSynPotentialShopBeginTimeAndEndTest4() throws Exception {
Timestamp beginTimestamp = PowerMockito.mock(Timestamp.class);
Timestamp endTimestamp = PowerMockito.mock(Timestamp.class);
PowerMockito.whenNew(Timestamp.class).withAnyArguments().thenReturn(beginTimestamp).thenReturn(endTimestamp);
when(endTimestamp.getTime()).thenThrow(RuntimeException.class);
redisService.getSynPotentialShopBeginTimeAndEnd();
}
It doesn't work either. These code don't have any red wavy underline ,but when I tried to run it, I got an exception like this:
org.mockito.exceptions.base.MockitoException:
Incorrect use of API detected here:
You probably stored a reference to `OngoingStubbing` returned by `when()` and called stubbing methods like `thenReturn()` on this reference more than once.
Examples of correct usage:
when(mock.isOk()).thenReturn(true).thenReturn(false).thenThrow(exception);
when(mock.isOk()).thenReturn(true, false).thenThrow(exception);
Is there another solution I can solve the problem? Anyway , only if the problem to be solved ,that's OK.

Try this
PowerMockito.whenNew(Timestamp.class).withAnyArguments().thenReturn(beginTimestamp,endTimestamp);
Instead of PowerMockito.whenNew(Timestamp.class).withAnyArguments().thenReturn(beginTimestamp).thenReturn(endTimestamp);

Related

How to initialize collection in one line?

I am creating my list like this and passing to a method withInitialListeners and then I don't see any compilation error and it works fine.
List<Host.StateListener> cassListener = new ArrayList<>(); // line 1
cassListener.add(new CassListener()); // // line 2
Builder clusterBuilder = Cluster.builder();
Cluster cluster =
clusterBuilder
.withInitialListeners(cassListener).build();
Now I was thinking to coming line1 and line2 in a single line and pass it directly to withInitialListeners method so I did something like this:
Builder clusterBuilder = Cluster.builder();
cluster =
clusterBuilder
.withInitialListeners(Arrays.asList(new CassListener())).build();
But with this approach it gives me compilation error as shown below:
The method withInitialListeners(Collection<Host.StateListener>) in the type Cluster.Builder is not applicable for the arguments (List<CassListener>)
What is wrong and how can I fix it? I am working with Java 7.
Ideally, you should change the signature of withInitialListeners to withInitialListeners(Collection<? extends Host.StateListener>).
If that is not an option, you can force the generic types of a method by placing explicit types in <…> before the method call:
Arrays.<Host.StateListener>asList(new CassListener())
As you can see, it’s pretty weird to write, and it may befuddle future developers who have to maintain it. The first option is preferred. But sometimes, explicit generic typing is unavoidable.

Why sometimes it gives exception but sometimes doesn't?

My program has two parts, one data structure and second operations.
Data Structure part is, basically and object & set of that object. This set is a class that extends ArrayList. Set and Objects are unique, what I mean is if I have a class named A then I have aSet which keeps the all A objects in it.
Operation part is doing some operations on those sets and most of the times it is also creates a new class in the runtime (write the class in a java file and compile it then call it from Reflect library functions e.g. constructor.newInstance(args);) and creates an object from new class then fill inside of it and return it. Since I didn't wanted to overwrite classes I use UUID trimmed for naming the new classes that created at the runtime.
I had noticed something odd. I run my code and it works, then I run it again and at the creation of set, it gives me "java.lang.IllegalArgumentException: wrong number of arguments". I run it again exception, again and again then I run it again then no exception. (Every time it created a new class like I wanted)
So why my code can act like this?
I am using Oracle Java 1.8 on Ubuntu 14.04 with Intellij Idea (tried also Eclipse no change).
Edit for code:
"I removed the codes unrelated to the problem"
And this is the part that gives error at my operation; (Initial innerInnerName is the random generated class name)
final String outerClassName = "" + initialInnerName + "Table";
final String innerClassName = "" + initialInnerName;
File file = new File("./src/");
URL url = file.toURI().toURL();
URL urls[] = new URL[]{url};
URLClassLoader loader1 = new URLClassLoader(urls);
Class<?> innerClass = loader1.loadClass(innerClassName);
Set<Template> newTable = null;
Class<?> outerClass = loader1.loadClass(outerClassName);
Constructor<?> constructorOfOuterClass = outerClass.getDeclaredConstructors()[0];
Object[] objArg = {innerClass,10};
newTable = (Set<Template>) constructorOfOuterClass.newInstance(objArg);
Edit 2
Exception being thrown at last line of last code which is:
newTable = (Set<Template>) constructorOfOuterClass.newInstance(objArg);
Well I had tried to do MCVE as much as possible.
Your "Outer Class" has two constructors, one that takes one argument and one that takes two. When you go to instantiate the outer class, you get the first in the list of constructors:
Constructor<?> constructorOfOuterClass = outerClass.getDeclaredConstructors()[0];
and then you try to invoke it with two arguments:
Object[] objArg = {innerClass,10};
newTable = (Set<Template>) constructorOfOuterClass.newInstance(objArg);
The problem is that the constructors aren't necessarily in the order you expect. No particular order is guaranteed, so sometimes you will get the one argument constructor and sometimes the two argument constructor. When you get the two argument constructor, all is well. But when you get the one argument constructor and invoke it with two arguments, well, you know all too well what happens then.
You need to determine which of the constructors is the one you want, and select it, rather than assuming that it is the first one in the list.

Invoke getMessageWaitingIndicator count of PhoneBase.java

I am trying to retrieve count of voicemail .For this I am trying to call getMessageWaitingIndicator method of PhoneBase.java.
My Code is as given below
Class<?> class2=Class.forName("com.android.internal.telephony.PhoneBase");
Method method=class2.getMethod("getMessageWaitingIndicator");
Boolean returnValue=(Boolean) method.invoke(class2);
But Everytime I am getting an exception as mentioned below :
java.lang.IllegalArgumentException: expected receiver of type com.android.internal.telephony.PhoneBase,
but got java.lang.class<com.android.internal.telephony.PhoneBase>
I don't understand it. How can I fix this issue?
The instruction:
method.invoke (stringValue);
needs the object in which the method will be invoked.
method = class2.getMethod('myFunction',String.class);
method.invoke(someInstanceOfMyActivity, stringValue);
Documentation:
http://docs.oracle.com/javase/6/docs/api/java/lang/reflect/Method.html
Edit.
You can also look at the answer to the very close question here:
Android Reflection Method Error

mockito callbacks and getting argument values

I'm not having any luck getting Mockito to capture function argument values! I am mocking a search engine index and instead of building an index, I'm just using a hash.
// Fake index for solr
Hashmap<Integer,Document> fakeIndex;
// Add a document 666 to the fakeIndex
SolrIndexReader reader = Mockito.mock(SolrIndexReader.class);
// Give the reader access to the fake index
Mockito.when(reader.document(666)).thenReturn(document(fakeIndex(666))
I can't use arbitrary arguments because I'm testing the results of queries (ie which documents they return). Likewise, I don't want to specify a specific value for and have a line for each document!
Mockito.when(reader.document(0)).thenReturn(document(fakeIndex(0))
Mockito.when(reader.document(1)).thenReturn(document(fakeIndex(1))
....
Mockito.when(reader.document(n)).thenReturn(document(fakeIndex(n))
I looked at the callbacks section on the Using Mockito page. Unfortunately, it isn't Java and I couldn't get my own interpretation of that to work in Java.
EDIT (for clarification):
How do I get get Mockito to capture an argument X and pass it into my function? I want the exact value (or ref) of X passed to the function.
I do not want to enumerate all cases, and arbitrary argument won't work because I'm testing for different results for different queries.
The Mockito page says
val mockedList = mock[List[String]]
mockedList.get(anyInt) answers { i => "The parameter is " + i.toString }
That's not java, and I don't know how to translate into java or pass whatever happened into a function.
I've never used Mockito, but want to learn, so here goes. If someone less clueless than me answers, try their answer first!
Mockito.when(reader.document(anyInt())).thenAnswer(new Answer() {
public Object answer(InvocationOnMock invocation) {
Object[] args = invocation.getArguments();
Object mock = invocation.getMock();
return document(fakeIndex((int)(Integer)args[0]));
}
});
Check out ArgumentCaptors:
https://site.mockito.org/javadoc/current/org/mockito/ArgumentCaptor.html
ArgumentCaptor<Integer> argument = ArgumentCaptor.forClass(Integer.class);
Mockito.when(reader.document(argument.capture())).thenAnswer(
new Answer() {
Object answer(InvocationOnMock invocation) {
return document(argument.getValue());
}
});
You might want to use verify() in combination with the ArgumentCaptor to assure execution in the test and the ArgumentCaptor to evaluate the arguments:
ArgumentCaptor<Document> argument = ArgumentCaptor.forClass(Document.class);
verify(reader).document(argument.capture());
assertEquals(*expected value here*, argument.getValue());
The argument's value is obviously accessible via the argument.getValue() for further manipulation / checking or whatever you wish to do.
With Java 8, this could be something like this:
Mockito.when(reader.document(anyInt())).thenAnswer(
(InvocationOnMock invocation) -> document(invocation.getArguments()[0]));
I am assuming that document is a map.

Problem with ArgumentCaptor and consecutive call to same methods (bug or feature?)

I'm having a problem with ArgumentCaptor not being able to record the
arguments when calling the same method a number of times.
Basically this does not seem to work:
List<Dummy> mList = mock(List.class);
Dummy dummy = new Dummy();
when(mList.get(anyInt())).thenReturn(dummy);
Dummy d = mList.get(12);
d.setName("John");
mList.add(d);
Dummy g = mList.get(10);
g.setName("Ben");
mList.add(g);
...
verify(mymock, times(3)).doStuff(captor.capture));
assertEquals("John", captor.getAllValues().get(0).getName());
assertEquals("Ben", captor.getAllValues().get(1).getName());
assertEquals("Don", captor.getAllValues().get(2).getName());
The value of getName() is always set to "Don".
I have also tried using InOrder, with the same outcome.
Feature (and me stupiud) or bug?
To better explain the issue I have created a use case:
http://pastebin.com/RE1UzJ4F
Cheers
iwein is correct; however, there are some situations (such as embedded systems) in which memory is scarce and you do not want to use or cannot use immutability.
A workaround I have found is to use a different mock for each invocation, then verify a list of mocks that each have one invocation.
List<Mock> mocks = new ArrayList<Mock>();
...init list w/ mocks using for loop...
List<Object[]> expectedArgs = new ArrayList<Object[]>();
..init list w/ desired args...
mocks.get(0).callMethod(1, 2);
...do that some more...
for(int i = 0; i < mocks.size(); i++) {
Object[] desiredArgs = expectedArgs.get(i);
verify(mocks.get(i)).callMethod((int) desiredArgs[0], (int) desiredArgs[1]);
}
It is not as pretty, but you do not have to make your classes immutable this way.
The java doc for ArgumentCaptor suggests what you are trying, so I'd say this is a bug. However, it is a bug in your code.
The problem is that you're changing the name of the same dummy each time you're invoking setName(..). I'd suggest that you make Dummy immutable and avoid setters wherever you can. That will avoid these types of bugs.
If you cannot make your Dummy immutable to force the issue you should at least pass a different instance from each get. Doing
when(mList.get(anyInt())).thenReturn(new Dummy(), new Dummy(), new Dummy());
Would fix the problem.
I had this problem and ended up using atLeastOnce, like so:
private ActionRequest getRequestedAction() {
ArgumentCaptor<ActionRequest> captor = ArgumentCaptor.forClass(ActionRequest.class);
verify(adapter, atLeastOnce()).requestAction(captor.capture());
return captor.getValue();
}

Categories