when(mongoCollection.updateOne(new Document("_id", anyString()), new Document("$set", new Document("_id", anyString()).append("funds", anyInt())), any(UpdateOptions.class)))
.then(i -> fundsByAccount.put(i.getArgument(0), i.getArgument(2)));
I have this java code i take in 4 matchers, but only 3 is expected, the first anyString() call and the second should be same, i want to reuse it so that i'll be able to do this in only 3 matchers call.
Code snippet and error
when(mongoCollection.updateOne(new Document("_id", anyString()), new Document("$set", any(Document.class).append("funds", anyInt())), any(UpdateOptions.class)))
.then(i -> fundsByAccount.put(i.getArgument(0), i.getArgument(2)));
I tried this but again this takes in 4 matcher calls, i need some way to reuse already captured values
Mockito cannot and will not "destructure" complex arguments for you. And it cannot match chained method calls (at least not in the way you expect). To set up stubs for a method call, you need to either provide 0 or matchers or exactly the number of formal parameters.
Your method has 3 parameters, so you need to pass 3 matchers:
when(mongoCollection.updateOne(any(Document.class), any(Document.class), any(Document.class)))
.then(i -> fundsByAccount.put(i.getArgument(0), i.getArgument(2)));
If both calls are important, you can either create the mock with Answers.RETURNS_DEEP_STUBS (read the disclaimer in its JavaDoc!); or set up updateOne to return another mock:
final Appender appendMock = Mockito.mock(Appender.class); // I don't know your type, use the correct one
when(mongoCollection.updateOne(any(Document.class), any(Document.class), any(Document.class)))
.thenReturn(appendMock);
when(appendMock.append("funds", anyInt()), any(UpdateOptions.class)))
.thenAnswer(....);
If you need your method call to be only matched when it is called with specific instances, you can use the Mockito#argThat matcher:
Mockito.argThat(doc -> Objects.equals(doc.getKey(), "_id")),
Mockito.argThat(doc -> Objects.equals(doc.getKey(), "$set")
&& Objects.equals(doc.getValue().getKey(), "funds"));
But maybe you have less trouble if you implement the interface of mongoCollection in your own custom class, which can then hold the state in memory. This might be easier, especially if you mock this class in many different tests.
Related
I'm calling a function from the database, named some_table_generating_function for the sake of simplicity, in order to cast the query into a select statement returning Field<Array<UUID>>, it forces me to use the val function of the DSL, and it creates a lot of boilerplate for doing a simple function invocation.
The following example works, but it seems to be overusing the val function, do you have any suggestions to cleanse this piece of code?
context
.select()
.from(
select(
// fields to be selected
)
.from(
Public.SOME_TABLE_GENERATING_FUNCTION(
`val`(someString.capitalise()),
`val`(someInt),
`val`(BigDecimal(someDecimalString)),
`val`(someInt),
`val`(BigDecimal(anotherDecimalString)),
`val`(BigDecimal(yetAnotherDecimalString)),
`val`(anotherInt),
`val`(someLong),
`val`(anotherLong),
// the important bit: uuid[] parameter expected for this parameter
field(
"ARRAY({0})::uuid[]",
select(A_TABLE.UUID.cast(String::class.java))
.from(A_TABLE)
.innerJoin(ANOTHER_TABLE)
.on(A_TABLE.UUID.eq(ANOTHER_TABLE.UUID))
.where(
// additional conditions
)
) as Field<Array<UUID>>
)
)
.join(THE_TABLE)
.asTable("inner_query")
)
.where(
// additional conditions
)
Background on the availability of convenience overloads
jOOQ's API can't overload all possible combinations of Tn vs Field<Tn> for larger numbers of n where n is the number of function parameters. For example:
1 parameter = 2 overloads (f(T1) and f(F<T1>)
2 parameters = 4 overloads (f(T1, T2), f(T1, F<T2>), f(F<T1>, T2), f(F<T1>, F<T2>)
3 parameters = 8 overloads
n parameters = 2^n overloads
While the DSL API often provides complete overloads for 2 parameters, it stops at 3 parameters, offering only 2 overloads in total:
An overload accepting only bind values
An overload accepting only expressions
It is the same with convenience overloads of generated user defined functions.
Possibility of a more verbose call syntax
Ordinary routines support both the convenience syntax and a more verbose call syntax:
// Convenience call
Routines.ordinaryRoutine(1, 2)
// Verbose way to call the routine, equivalent to the above
val r = OrdinaryRoutine()
r.param1 = 1
r.param2 = 2
This currently isn't available for table valued functions, which only know the "convenience syntax". Might be worth looking into generating alternatives to calling table valued functions:
https://github.com/jOOQ/jOOQ/issues/14508
Workarounds
You could create an auxiliary function that calls your function but accepts the first set of parameters in the form of a UDT (CREATE TYPE), so you have to wrap the single UDT argument in DSL.val() only a single time. This doesn't scale too well in terms of function API design, but it works around this problem
You could use plain SQL templating for the function call (from("f(?, ?, ... {0})", someString.capitalise(), someInt, ..., field(...))), since you're already using a plain SQL template. This won't be type safe, though.
You could extend the JavaGenerator to generate an extra overload for your specific case
Personally, I don't find any of these workarounds very practical. Since you probably don't have this case very often, I'd stick with the original call using explicit val calls
I'm trying to test the method on mocked object getting called in the expected order or not. Below is the simplified example:
#Test
public void test() {
List<String> mockedList = Mockito.mock(List.class);
for (int i = 0; i < 5; i++) {
mockedList.add("a");
mockedList.add("b");
mockedList.add("c");
}
// I want only this to pass.
InOrder inOrder1 = Mockito.inOrder(mockedList);
inOrder1.verify(mockedList).add("a");
inOrder1.verify(mockedList).add("b");
inOrder1.verify(mockedList).add("c");
// I want this to fail.
InOrder inOrder2 = Mockito.inOrder(mockedList);
inOrder2.verify(mockedList).add("c");
inOrder2.verify(mockedList).add("b");
inOrder2.verify(mockedList).add("a");
}
Although the verifying order (c -> b -> a) is different from the invocation order (a -> b -> c), this test passes. This is because Mockito verifies if method2 called anywhere AFTER method1, but not immediately (i.e., no other method called in between). As I'm adding elements multiple times, this is very much possible. Which means, Mockito InOrder passes for b -> a -> c -> a -> c -> b -> c -> b -> a ...
But I want this to fail, and make sure the order is always a -> b -> c -> a -> b -> c -> a -> b -> c ...
Update: Proper way to verify is to verify the order same number of iterations (summary of accepted answer):
for (int i = 0; i < 5; i++) {
inOrder1.verify(mockedList).add("a");
inOrder1.verify(mockedList).add("b");
inOrder1.verify(mockedList).add("c");
}
// fail the test if we missed to verify any other invocations
inOrder1.verifyNoMoreInteractions();
The thing is that you need to add
inOrder.verifyNoMoreInteractions();
With your loop you generate calls like
add(a)
add(b)
add(c)
add(a)
add(b)
add(c)
When you then check
inOrder.verify(mockedList).add("b");
inOrder.verify(mockedList).add("c");
inOrder.verify(mockedList).add("a");
It matches the calls (add(b), add(c), add(a)). The other calls are not checked.
add(a)
add(b)
add(c)
add(a)
add(b)
add(c)
So I think you have to options:
1) verify all calls a, b, c, a, b, c
2) verify that no more interactions happen to your mock
BTW if you change the verification to
inOrder.verify(mockedList).add("c");
inOrder.verify(mockedList).add("b");
inOrder.verify(mockedList).add("a");
it will fail as it does not match the calls :-)
A non answer here: you are going down the wrong path (at least for the given example):
Meaning: when you create an "API", you want to achieve "easy to use, hard to mis-use". An API that requires methods to be called in a certain order doesn't achieve that. Thus: feeling the need to check for order programmatically could be an indication that you are doing "the wrong thing". You should rather design an API that "does the right thing" instead of expecting users of your code to do that for you.
Beyond that: when you are testing lists, you absolutely do not want to use mocking in the first place.
You want to make sure that elements get added to a list in a specific order? Then a simple
assertThat(actualList, is(expectedList));
is the one and only thing your test should check for!
Meaning: instead of testing an implementation detail (add() gets called with this and that parameter, in this and that order), you simply check for the observable outcome of that operation. You don't care in which order things get added, and maybe re-setted and updated, you only care for the final result!
Given the comment by the OP: when you have to process certain calls/objects "in order", then you should design an interface that allows you communicate that intent. You are only testing your intent via unit tests. That is of course a good start, but not sufficient!
Basically, there are two concepts that could work for you:
Sequence numbers: when objects come in sequentially, and order matters, then each object should receive a unique (ideally ascending) sequence number. And then each step that processes elements can simply remember the last sequence number that was processed, and if a lower one comes in, you throw an exception.
Sequences of "commands". The OP wants to make sure that method calls happen in order. That is simply not a helpful abstraction. Instead: one could create a Command class (that executes "something"), and then create different subclasses for each required activity. And then your processor simply creates a List<Command>. And now testing boils down to: generating such a sequence, and checking that each entry is of a given type.
I have a bit of logic that needs to be tested such as:
{
...
A.add("1");
...
A.add("what ever");
...
A.add("2");
A.delete("5");
...
}
I have already mocked A in my test and I can test the add method is called once on argument ("2") such as:
Mockito.verify(mockedA).add("2");
My question is how can I test if I can verify the last call on method add is add("2") instead of other arguments.
Since the test above can't catch if somebody by accident adds another call such as add("3") in the last. Please notice that we don't care about other method invocations on A again afterwards. We also don't care about the times of the method called, the sequence of the methods called. The key point here is if we can verify the last true argument on a certain method of a certain mockedObject.
If you ask why do you need such functionality, I'd say in real world we might need to handle some logic that set something and the last set wins, and in order to avoid someone by accident set some other thing unexpected and I'd like to use our UT to catch this. And in order not to make the test too complex and neat, so I only expect to verify the last call on a certain method of a object instead verify something like order/noMoreInteractions/AtMostTimes and so on.
About the order of the invocations
By default, Mockito.verify() doesn't matter of the invocation order.
To take it into consideration, wrap the mock in an InOrder instance and perform the invocation verification on this instance.
About the no more interations
If the mock is no more invoked after the methods that you want to verify, you could use Mockito.verifyNoMoreInteractions(Object... mocks) that checks if any of given mocks has any unverified interaction such as :
InOrder inOrder = Mockito.inOrder(mockedA);
inOrder.verify(mockedA).add("1");
inOrder.verify(mockedA).add("2");
Mockito.verifyNoMoreInteractions(mockedA);
If the mock may still be invoked after the methods that you want to verify, you could add after your verifies an invocation to verify(T mock, VerificationMode mode) by passing a VerificationMode that checks that at most 2 invocations were performed.
InOrder inOrder = Mockito.inOrder(mockedA);
inOrder.verify(mockedA).add("1");
inOrder.verify(mockedA).add("2");
Mockito.verify(mockedA, Mockito.atMost(2)).add(Mockito.anyString());
A warning about your think and this way of mocking
Since the test above can't catch if somebody by accident adds another
call such as add("3") in the last.
Mockito provides a powerful and broad toolkit to work with mocks. Some features such as verify and more particularly verify that no more interaction was detected about a mock or a specific method of the mock make your test more complex to read and to maintain.
As well as, currently you want to check that the invocations on a mock were performed in a specific order. But you generally want to use these checks only as required that is according to the business/logic scenarios, not technical invocations.
For example supposing that in the tested method you have a case where for business reasons the mocked method is invoked 3 times and another case where the mocked method is invoked 2 times. It could make sense to check that it is only invoked 2 times and not more in the case with two expected invocations.
But in a general way, you should be cautious that your unit test doesn't overuse mocking verify that could look like as a assertion on the description of the flow and not a assertion on the behavior/logic.
Thanks #staszko032, inspired by the ArgumentCaptor, instead of getAllValues and verify the sequence, we can use getValue of captor since captor's getValue always get the last true argument. We can do it like this:
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
Mockito.verify(mockedA, Mockito.atLeastOnce()).add(captor.capture());
Assert.assertEquals("2", captor.getValue());
What this looks like to me is that you are mocking a data class. In my experience it's better to leave (stateful) data classes and mock (stateless) services. This way, you can verify that the method under test produces the correct data, rather than just verifying a series of invocations. Along with testdata builders (making it easy to instantiate your data classes with some default state, using builder pattern for instance), it becomes real easy to write tests.
If you do need to mock, the only way to test what you want is to use InOrder, and verify each of the invocations on the mock, and end with verifyNoMoreInteractions.
I've ended up implementing a new VerificationMode to do this. Here's the code in case it's useful to anyone.
class MostRecently implements VerificationMode {
#Override
public void verify(VerificationData data) {
MatchableInvocation target = data.getTarget();
List<Invocation> invocations = data.getAllInvocations();
if (invocations.isEmpty()) {
throw wantedButNotInvoked(target);
}
List<Invocation> targets = findInvocations(invocations, target);
if (targets.isEmpty()) {
throw wantedButNotInvoked(target);
}
Invocation lastInvocation = invocations.get(invocations.size() - 1);
if (target.matches(lastInvocation)) {
return;
}
ListIterator<Invocation> iterator = invocations.listIterator(invocations.size());
Invocation previous = iterator.previous();
Invocation undesired = previous;
while (!target.matches(previous)) {
undesired = previous;
previous = iterator.previous();
}
Invocation lastGoodInvocation = previous;
throw new MockitoAssertionError(join(
"Wanted most recent on '" + lastGoodInvocation.getMock() + "' to be " + lastGoodInvocation.getMethod(),
"No more interactions wanted after " + lastGoodInvocation.getLocation(),
"but found this interaction on mock '"
+ MockUtil.getMockName(undesired.getMock()) + "':",
undesired.getLocation(),
allLocations(invocations)));
}
static String allLocations(List<Invocation> invocations) {
StringBuilder sb = new StringBuilder("***\nFor your reference, here is the list of all invocations.\n");
int counter = 0;
for (Invocation i : invocations) {
sb.append(++counter).append(". ");
sb.append(i.getLocation()).append("\n");
}
return sb.toString();
}
}
Simplifying a bit, our system has two parts. "Our" part, which in turn uses an lower level part implemented by another team (in the same codebase). We have a fairly complicated functional test setup, where we wrap the entry points to the lower level in spy objects. In positive tests we use the real implementation of that level, but we mock calls that should fail with some predefined error.
Now I am trying to add support for more complicated scenarios, where I would like to add an artificial delay for the calls made to the underlying level (on a fake clock obviously). To do this I would like to define a mock that would (1) Call the real implementation (2) Get the resulting Future object that is returned and combine it with a custom function that would inject the delay accordingly. So Ideally I would like to have something like:
doAnswer(invocationOnMock ->
{
result = call real method on mySpy;
return Futures.combile(result, myFunction);
}).when(mySpy).myMethod();
How can I achieve it?
As for me the easiest way it's just to save the link to the read object when you initialize your Spy object:
Foo realFoo = new Foo();
Foo spyFoo = Mockito.spy(realFoo);
Now you can stub it like this:
doAnswer(invocation -> realFoo.getSome() + "spyMethod").when(spyFoo).getSome();
One more way is to call invocation.callRealMethod():
doAnswer(invocation -> invocation.callRealMethod() + "spyMethod").when(spyFoo).getSome();
But in this case you may need to cast the return value as long as invocation.callRealMethod() returns Object.
I have started working on a BDD project using JBehave. I need to build a sequence of methods to be called based on the steps "Given", "When" and finally execute them in "Then". A sample would be like
Given a user logins as a premium user
When he adds an item to the cart
Then he gets a special discount
For the above scenario, I would have to build method call sequence based on "Given" / "When" and then execute the same in "Then"
E.g.
List<Executable> sequenceList
#Given
public void execGiven()
{
A a = new A();
a.call1()
a.call2()
B b = new B();
b.call3();
}
#When
public void execWhen(){
C c = new C();
c.call4();
//...few more methods
#Then
public void execThen(){
//Add some methods to the list of executables
D d = new D();
d.call5();
Assert if everything successful
}
The problem I am facing is that the framework we are using(in built and in use) cannot be used to partially execute the method call sequences in each Step of a story. Rather, I have to execute them as a whole sequence( from a.call1 to d.call5).Also another issue is that I dont want to hardcode the method calls for each step instead call them based on some config at runtime.
My Approach.
Instead of running these methods (a.call1 , a.call2) in each step, add them to a list of Methods and execute them in "Then" using reflections. Also use annotations like
#Sequence(step="Login" , sequenceId=1) for each method so that at runtime I can build a list of calls to be made.
What would be a good approach considering that any change in the method call sequence is less painful to change. I had few approaches in mind
Use annotations to wire the sequence
Use xml to wire the sequence
Use a text file to mention the sequence(almost same as above)
Is there any better approach to build the graph in the runtime and execute the sequence? Also any drawbacks of the same?
Thank You