Is this possible?
I tried with EasyMock.expectLastCall().times(0); but EasyMock complains that times must be >=1
You could use .andThrow(new AssertionFailedError()).anyTimes(); - this is the same exception that Assert.fail() throws, but is less verbose than making an Answer.
with easymock 3.0, you need to add a .anyTimes() on the expectLastCall or the test will fail:
Expectation failure on verify: myMethod(): expected: 1, actual: 0`
based on nkr1pt example:
expectLastCall().andAnswer(new IAnswer() {
public Object answer() {
Assert.assertFail();
return null;
}
}).anyTimes();
The fact that some method is not called is controlled by Mock or StrictMock. They will throw an exception, when that not recorded method is called. This problem occurs only when using NiceMocks, where default values are returned when calling for not recorded methods.
So a solution can be not to use NiceMocks.
Looks like a bug to me. The internal class Range does not allow to set a maximum less than 1.
Couldn't you mock that method, and just call Assert.fail() ?
If you expect your method not to be called then just don't record it. But I agree it won't work with a nice mock.
I managed to come up with a solution:
expectLastCall().andAnswer(new IAnswer() {
public Object answer() {
Assert.assertFail();
return null;
}
});
Related
I have a class which contains the following three methods:
void add(Service... objs)
void add(Collection<Service> objs)
void add(Stream<Service> objs)
As you might expect, these all support the adding of zero or more objects, which can be specified individually or as part of an array, a collection or a stream. The first two variants create a stream from their arguments, and pass them to the third variant which actually does the adding.
In testing an object that uses this class, I have created a Mockito mock object to represent an instance of this class, using Spring's #MockBean annotation. I can see in the debugger that the object under test contains the mock object, and that the call I am expecting (with a single argument of type Service) is being addressed to the mock. Because the method that should be called is the first variant (the varargs one), and I know that varargs parameters are a little tricky, I coded the test to check that the mock is called with the correct parameter as follows:
ArgumentCaptor<Service> captor = ArgumentCaptor.forClass(Service.class);
verify(theMock).add(captor.capture());
assertThat(captor.getAllValues()).containsExactly(expectedService);
However, when I run this code the assertion fails because the List returned by captor.getAllValues() contains not a Service, but a Stream: the failure message says:
java.lang.AssertionError:
Expecting:
<[java.util.stream.ReferencePipeline$Head#2cfe272f]>
to contain exactly (and in same order):
<[com.xxx.data.Service#37c5]>
but some elements were not found:
<[com.xxx.data.Service#37c5]>
and others were not expected:
<[java.util.stream.ReferencePipeline$Head#2cfe272f]>
When I run the code in the debugger, I can see that the call from the object under test to add(Service...) invokes the real implementation; this invokes add(Stream<Service>) and it is that call which is intercepted by the mock. That explains why I am seeing the failure, but I don't understand why the mock is failing to intercept the original call, or what I can do to make it do so.
Update your ArgumentCaptor to accept Service[]
ArgumentCaptor<Service[]> serviceCaptor = ArgumentCaptor.forClass(Service[].class);
And assert
Service[] actualServices = serviceCaptor.getAllValues();
assertEquals(actualServices.length, 1);
assertEquals(actualServices[0], service);
And it's best practice to use ErrorCollector in Junit to assert more than one
assert and SoftAssect in Testng and call after your assertion softAssert.assertAll()
I have come up with a workaround to the problem, but the actual problem still exists and I think it is probably a Mockito bug (raised as https://github.com/mockito/mockito/issues/1929).
The workaround is to add this method to my test class. I've added a generic method because it is not just a call to the add() method that has the problem, but also a call to a similar overloaded remove() method that takes String arguments.
private <T, V> void verifyCall(T mock, BiConsumer<T, V> call,
V expectedArg, Class<V> type)
{
ArgumentCaptor<V> captor = ArgumentCaptor.forClass(type);
call.accept(verify(mock), captor.capture());
List<?> values = captor.getAllValues();
try {
assertThat(values.get(0)).isEqualTo(expectedArg);
} catch (AssertionFailedError ex) {
assertThat((Stream<V>) values.get(0)).containsExactly(expectedArg);
}
}
This should work whether the call intercepted by the mock was to the varargs variant of the method (as it should be) - in which case the assertion in the body of the try block will not throw an exception - or to the Stream variant (as it currently is) - in which case the assertion in the body will throw an exception and the assertion in the catch block will be executed.
Then, when I want to verify that my mock's add() method was called with the expected Service object, I do so with:
verifyCall(theMock, Datastore::add, expectedService, Service.class);
And similarly, for the remove() method:
verifyCall(theMock, Datastore::remove, expectedDeletedKey, String.class);
Very pleasingly, when I finally got this working the test failed because I had made a mistake in the method under test. Which made it all worthwhile.
D'oh. I failed to spot that the two varargs methods were declared as final. Removed this and it all works as expected.
I am using Mockito to mock a method in the same class for which I am writing test. I have seen other answers on SO (Mocking method in the same class), but probably I am misunderstanding them, since I running into issues.
class Temp() {
public boolean methodA(String param) {
try {
if(methodB(param))
return true;
return false;
} catch (Exception e) {
e.printStackTrace();
}
}
}
My Test method:
#Test
public void testMethodA() {
Temp temp = new Temp();
Temp spyTemp = Mockito.spy(temp);
Mockito.doReturn(true).when(spyTemp).methodB(Mockito.any());
boolean status = temp.methodA("XYZ");
Assert.assertEquals(true, status);
}
I however get the expection printed out because definition of methodB gets executed.
My understanding is definition of methodB would get mocked by using spyTemp. However that does not appear to be the case.
Can someone please explain where I am going wrong?
The first issue is that you have to use spyTemp object to expect something from Mockito. Here it is not the same as test. spyTemp is wrapped by the Mockito object temp.
Another issue is that you stub only methodB(), but you are trying to run methodA(). Yes in your implementation of methodA() you call methodB(), but you call this.methodB(), not spyTemp.methodB().
Here you have to understand that mocking would work only when you call it on the instance of temp. It's wrapped by a Mockito proxy which catches your call, and if you have overriden some method, it will call your new implementation instead of the original one. But since the original method is called, inside it you know nothing about Mockito proxy. So your "overriden" method would be called only when you run spyTemp.methodB()
This should work:
Mockito.doReturn(true).when(spyTemp).methodB(Mockito.any());
boolean status = spyTemp.methodA("XYZ");
You created a spy and mocked methodB(). That is correct! But you called methodA() on the original object. To get the correct result call it on the spy
boolean status = spyTemp.methodA("XYZ");
Note the following from Mockito documentation:
Mockito does not delegate calls to the passed real instance, instead
it actually creates a copy of it. So if you keep the real instance and
interact with it, don't expect the spied to be aware of those
interaction and their effect on real instance state. The corollary is
that when an unstubbed method is called on the spy but not on the
real instance, you won't see any effects on the real instance.
This is referring specifically to your situation. You keep a reference to temp and then call its methodA. Mockito is not spying on that instance at all; it's spying on spyTemp. So the normal methodB is called.
Note that you should avoid partial mocks altogether for new code.
Collection<T_SI_IDABAREME> tSiIdabaremes;
DAO_F_IDA_DESC mockDaoFIdaDesc
prepareExpects(){
expect(mockDaoTSiIdabareme.findByDate(isA(Date.class)))
.andReturn(searchByParameter(tSiIdabaremes, date));
}
Is it possible to use the date that will be passed to the findByDate in the andReturn?
PS: This is a service test class and I'm doing it in a way to bypass the database.
whenever you use expect method like this
Easymock.expect(someMethod(Date.Class)).andReturn(something);
you are instructing compiler to mock all calls to that method whenever ANY object of Date class is passed as parameter,and you will not be able to use that object in return expression.
on the other hand if you have something like this,
Easymock.expect(someMethod(someSpecificDateObject)).andReturn(someSpecificDateObject);
you are instructing the compiler to mock this method call ONLY when a specific object of Date class is passed as parameter(someSpecificDateObject in this case) and you will be able to use this parameter while returning, because you know that method gets mocked only when this object is passed.
You can use second option if it is favourable to you,but with first option what you ask is not possible.
Hope this helps!
Good luck!
Instead of:
expect(mockDaoTSiIdabareme.findByDate(isA(Date.class)))
.andReturn(searchByParameter(tSiIdabaremes, date));
I should have put
expect(mockDaoTSiIdabareme.findByDate(isA(Date.class)))
.andAnswer(new IAnswer<Collection<T_SI_IDABAREME>>() {
public Collection<T_SI_IDABAREME> answer() throws Throwable {
return searchByParameter((Date)getCurrentArguments()[0]);
}
}
);
Which will only look for the return value when the method is being exectued and then we can use getCurrentArguments() to retrieve the arguments passed to the method.
You can find more about this in the EasyMock Documentation.
I am experiencing a certain bug in JUnit/JMock. I am trying to mock a couple of objects and then assert that all expectations is satisfied. I am running a simple test such as :
#Test
public void sellingPutOptionProductDoesNotCauseDisclosure() throws PositionVerificationException, DataLoadException, MissingPriceException {
final OptionProduct optionProduct = setupOptionProduct();
context.assertIsSatisfied();
}
private OptionProduct setupOptionProduct() {
final Option optionProduct = context.mock(Option.class);
context.checking(new Expectations() {
{
oneOf(optionProduct).getUnderlyingProduct();
will(returnValue(new Object()));
}
});
return optionProduct;
}
The Option is an object and I am using Mockery like this:
context = new Mockery() {
{
setImposteriser(ClassImposteriser.INSTANCE);
}
};
If I run the above test I am gettiing Test passed, where JVM does not terminate and the last print out in console is:
Exception in thread "main"
ANy ideas what might be causing this?
I'm a little late to the party, but I just had a similar problem and was able to track down the cause.
Normally, when a method is called that is not part of the expectations, JMock builds the log telling you what was expected that was not found. In my case, it tried to create that log message after encountering an unexpected call. The act of creating the log message threw an exception, which got JMock all confused and it reported that the test passed, when it had actually failed.
In my case, the reason that the exception was thrown was that one of the parameters being passed to the "unexpected" function call was an instance of a class. That class was initialized, in part, with mocked objects. When JMock was trying to build the error message to tell me about the unexpected invocation, it needed to describe the parameter. Usually it will say something like unexpected invocation: myobject.myMethod(param1,param2).
Because param1, in my case, contained member variables that were mock objects, and the param1 class did not define toString(), the default, Object.toString() was used.
Object.toString() is defined as: return getClass().getName() + "#" + Integer.toHexString(hashCode());
My implementation of hashcode for param1 was using some of those mocked objects. Those calls on the mocked objects to calculate the hashcode were 'unexpected' invocations themselves, leading JMock to throw an exception when trying to describe the test failure to me.
Unfortunately, instead of recognizing this condition and still reporting as much of the failure as it could, JMock seemed to give up altogether and report the test as passing and offhandedly mention Exception in thread "main."
To see if this is happening to you, I recommend you check the parameters involved in the offending function calls. If any of them are classes, not interfaces, you should see if their use of equals / hashcode / toString use any suspicious calls to member variables that may not be playing nice with how your scenario is being mocked.
Testing in Java (using Mockito and Powermock but willing to use anything that will solve this). I have an object that has the following signature:
public class MyClass {
public void doRun() {
//Do work
}
public int numberComplete() {
//Return number of items complete
}
}
The "doRun" method gets a list of items and "completes" them (each taking a considerable amount of time). In order to "get" and "finish" an item, a mock manager is used, so I have tests like:
#Test public void managerIsInformedOfEachFinishedItem() {
task.doRun();
verify(mockManager, times(3)).finish((Item)any());
}
At the end of this, I can call "task.numberComplete()" and see that indeed, the task returns 3. But, what I'd really like to do is something like:
#Test public void managerIsInformedOfEachFinishedItem() {
int count1, count2;
when(mockManager.finish(item1).thenSet(count1 = task.numberComplete());
when(mockManager.finish(item2).thenSet(count2 = task.numberComplete());
task.doRun();
assertEquals(1, count1);
assertEquals(2, count2);
}
I realize this may not be something that's already available. But if you were going to try to implement something like this (regardless of the syntax - I don't care how clean the test reads initially), how would you do it? Any suggestions/ideas are appreciated!
Instead of using a third-party mock framework for the manager, you could implement your own mock manager that does the verification for you in its finish method. Bear in mind that if finish will get called in a different thread, then you shouldn't put the assertEquals there because an AssertionError thrown in that thread will most likely be ignored. Instead, you could store the success/failure result in a member variable (property) of your mock manager and check that from your test afterward. (Don't forget to synchronize access to that shared result value or use an atomic to hold it.)