public class EventCombiner<Target,Event>
extends java.lang.Object
implements java.util.function.Consumer<Target>
Class represents an abstraction that performs a call to a stubbed mock method at one and, and combines
captured arguments into a single "event" at another end. Shall be used along with the EventCollector
The main idea and a need for such an abstraction arise from the fact that EventCollector is abstract
enough to work with only a single "event" (moreover listeners with a single argument is 95% of use cases for
the collector). But methods with multiple argument shall be supported. Just in case.
EventCombiner represents a call to a method with N>0 arguments, and a combinator function that can combine
these N arguments into a single instance of some type: <Event>. So when user requests a creation
of the EventCombiner - he specifies how many arguments will be captured; as a result combiner generates specified
number of Mockito's ArgumentCaptor instances. Then user has to provide a call to a single specific method
in the form of a BiConsumer where first argument is an instance of the type <Target>
and the second argument is an ArgumentCaptor[] array of the specified size. In this consumer user
should perform a method call and specify which arguments exactly he wants to capture. All provides captors are
of the same basic unknown type <?>, so user have to perform manual cast for each captor. Also user has to provide
a function that takes an Object[] array as argument and returns an instance of the specified type <Event>.
This function will be called whenever getValue() is called, and will receive array of the same size N
specified at the construction; this array will contain all the objects returned by the ArgumentCaptor instances.
See method forCaptors(int, BiConsumer, Function) for described basic functionality. But also take a look
at the forValues(int, BiConsumer, Function) method, allowing you to perform almost the same operation,
but automatically initializing captors.
See method forCaptor(BiConsumer) allowing to perform a single selective capture.
Also note all the create(BiConsumer) methods with a single argument. Those provide the easiest way
to create a combiner for multiple arguments.
| Modifier and Type | Method and Description |
|---|---|
void |
accept(Target t)
This method delegates specified target to the
getMethodCall() consumer along with captors
received from getCaptors(). |
static <T,E> EventCombiner<T,E> |
create(java.util.function.BiConsumer<T,E> methodCall)
The easiest way to create a combiner that generates a single captor and captures a single argument.
|
static <T,A,B> EventCombiner<T,Tuple2<A,B>> |
create(Consumer3<T,A,B> methodCall)
The easiest way to create a combiner that generates two captors and captures two sequential arguments.
|
static <T,A,B,C> EventCombiner<T,Tuple3<A,B,C>> |
create(Consumer4<T,A,B,C> methodCall)
The easiest way to create a combiner that generates three captors and captures three sequential arguments.
|
static <T,A,B,C,D> |
create(Consumer5<T,A,B,C,D> methodCall)
The easiest way to create a combiner that generates four captors and captures four sequential arguments.
|
static <T,E> EventCombiner<T,E> |
forCaptor(java.util.function.BiConsumer<T,org.mockito.ArgumentCaptor<E>> methodCall)
Pure form of the event collector (backed by the
create(BiConsumer) method) allows
to stub only methods with one argument. |
static <T,E> EventCombiner<T,E> |
forCaptors(int numberOfEvents,
java.util.function.BiConsumer<T,org.mockito.ArgumentCaptor<?>[]> methodCall,
java.util.function.Function<java.lang.Object[],E> combiner)
Basic factory method for an
EventCombiner (see class documentation for basic understanding). |
static <T,E> EventCombiner<T,E> |
forValues(int numberOfEvents,
java.util.function.BiConsumer<T,java.lang.Object[]> methodCall,
java.util.function.Function<java.lang.Object[],E> combiner)
Basically equal to the
forCaptors(int, BiConsumer, Function) with only difference that
specified BiPredicate method call receives an array of matchers (Object[]) instead of
captors. |
org.mockito.ArgumentCaptor<?>[] |
getCaptors()
Copy of array of all generated
ArgumentCaptor instances. |
java.util.function.Function<java.lang.Object[],Event> |
getCombiner()
A function that will be used to combine captured argument into a single instance of the
<Event> type. |
java.util.function.BiConsumer<Target,org.mockito.ArgumentCaptor<?>[]> |
getMethodCall()
BiConsumer representing a call to the linked method; used to delegate target call. |
Event |
getValue()
This method requests last captured value from all the captors received from
getCaptors()
and then applies getCombiner() function to them. |
java.lang.String |
toString() |
public static <T,E> EventCombiner<T,E> forCaptors(int numberOfEvents, java.util.function.BiConsumer<T,org.mockito.ArgumentCaptor<?>[]> methodCall, java.util.function.Function<java.lang.Object[],E> combiner)
Basic factory method for an EventCombiner (see class documentation for basic understanding).
numberOfEvents - - number of argument captors to be generated by the combinermethodCall - - a consumer that will take an instance of the target class and array of captors
and perform a call to a method to be stubbed.combiner - - the combinator function that will take an array of captured argument and convert them
into a single instance of the specified "event" type <E>forCaptor(BiConsumer),
forValues(int, BiConsumer, Function),
create(BiConsumer)public static <T,E> EventCombiner<T,E> forCaptor(java.util.function.BiConsumer<T,org.mockito.ArgumentCaptor<E>> methodCall)
Pure form of the event collector (backed by the create(BiConsumer) method) allows
to stub only methods with one argument. But using a BiPredicate to indicate stubbed method allows you
to call any method where matcher (passed into a predicate) might be passed as one
of the multiple arguments. Example:
interface Listener {
void event(Integer i, String s);
}
EventCombiner<Listener, String> collector =
EventCombiner.create((l,s) -> l.event(Matchers.any(), s));
The problem with this example is that it won't work as expected. Specifics of the Mockito functionality
require matchers to be created in the same order as matched arguments. And because the matcher specified
in the predicate by an event collector was created before the one created manually - it still will
try to match the first argument of the called method.
To perform such a capture method forCaptors(int, BiConsumer, Function) might be used,
but the problem arise is that user will have to specify the number of required captors: 1, and the to specify
a BiPredicate that takes an array of captors, and then a combinator function, that casts an object to the
required type. All of this might be avoided, since we definitely use only a single captor.
So BiPredicate accepted by this method takes an instance of the ArgumentCaptor
as a second argument. User will have to call ArgumentCaptor.capture() on it to specify the argument
to be collected. Example:
interface Listener {
void event(Integer i, String s);
}
EventCombiner<Listener, String> collector =
EventCombiner.forCaptor((l,c) -> l.event(Matchers.any(), c.capture()));
In this example combiner's matcher is initiated after the matcher created by the Matchers.any() call.
As a result it provides you an interesting functionality (relatively easy to implement) that allows you
to capture one of the arguments, completely ignoring others (Mockito's Matchers got
to be used manually to create matchers for other arguments).
forCaptors(int, BiConsumer, Function)public static <T,E> EventCombiner<T,E> forValues(int numberOfEvents, java.util.function.BiConsumer<T,java.lang.Object[]> methodCall, java.util.function.Function<java.lang.Object[],E> combiner)
Basically equal to the forCaptors(int, BiConsumer, Function) with only difference that
specified BiPredicate method call receives an array of matchers (Object[]) instead of
captors. So user don't have to manually call ArgumentCaptor.capture() method on all of them.
Note: since all captors get initiated before the call to the consumer - they will definitely
match only N first arguments of the called method. Where N is the number of generated
captors. This means that this method will not suffice in case you want to captor non-sequential
arguments!
public static <T,E> EventCombiner<T,E> create(java.util.function.BiConsumer<T,E> methodCall)
The easiest way to create a combiner that generates a single captor and captures a single argument.
Specified BiConsumer should perform a single method call on the first argument with a second
argument as method parameter.
Usability method creating a combiner without any actual combining. Single captor is created, single argument is captured and then just gets cast to the required type.
create(Consumer3),
create(Consumer4),
create(Consumer5)public static <T,A,B> EventCombiner<T,Tuple2<A,B>> create(Consumer3<T,A,B> methodCall)
The easiest way to create a combiner that generates two captors and captures two sequential arguments.
Specified Consumer3 should perform a single method call on the first argument with a second and third
arguments as method parameters.
Captured arguments are combined into a single Tuple2 instance.
create(BiConsumer),
create(Consumer4),
create(Consumer5)public static <T,A,B,C> EventCombiner<T,Tuple3<A,B,C>> create(Consumer4<T,A,B,C> methodCall)
The easiest way to create a combiner that generates three captors and captures three sequential arguments.
Specified Consumer4 should perform a single method call on the first argument with a second, third, and
fourth arguments as method parameters.
Captured arguments are combined into a single Tuple3 instance.
create(BiConsumer),
create(Consumer3),
create(Consumer5)public static <T,A,B,C,D> EventCombiner<T,Tuple4<A,B,C,D>> create(Consumer5<T,A,B,C,D> methodCall)
The easiest way to create a combiner that generates four captors and captures four sequential arguments.
Specified Consumer5 should perform a single method call on the first argument with a second, third,
fourth, and fifth arguments as method parameters.
Captured arguments are combined into a single Tuple4 instance.
create(BiConsumer),
create(Consumer3),
create(Consumer4)public org.mockito.ArgumentCaptor<?>[] getCaptors()
Copy of array of all generated ArgumentCaptor instances.
public java.util.function.BiConsumer<Target,org.mockito.ArgumentCaptor<?>[]> getMethodCall()
BiConsumer representing a call to the linked method; used to delegate target call.public java.util.function.Function<java.lang.Object[],Event> getCombiner()
<Event> type.public void accept(Target t)
getMethodCall() consumer along with captors
received from getCaptors().accept in interface java.util.function.Consumer<Target>public Event getValue()
getCaptors()
and then applies getCombiner() function to them. Result is returned.public java.lang.String toString()
toString in class java.lang.Object