[mockito] Either ... or ... verification

1,592 views
Skip to first unread message

Maciej Biłas

unread,
May 20, 2010, 8:35:27 AM5/20/10
to moc...@googlegroups.com
Hey,

If it possible in Mockito to verify that the following interaction happened:

for a class defined below
interface Foo {
void a();
void b();
}

either method a() or method b() was invoked.

Many thanks in advance for your help.

Best wishes,
Maciej
--
Maciej Biłas

--
You received this message because you are subscribed to the Google Groups "mockito" group.
To post to this group, send email to moc...@googlegroups.com.
To unsubscribe from this group, send email to mockito+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/mockito?hl=en.

szczepiq

unread,
May 20, 2010, 8:59:31 AM5/20/10
to moc...@googlegroups.com
Hey

Not directly... Possibly you could stub the methods to flag some property and then assert on it.

Quite scary use case...

Cheers ;)
Szczepan

Rajesh Kalluri

unread,
May 20, 2010, 9:36:29 AM5/20/10
to moc...@googlegroups.com
Is there a boolean method on the system under test that decides whether a() or b() is called.

If so you can spy and stub that method to  verify interactions with a() and b()

Have fun
Raj
--
4327 125th st
Urbandale
IA-50323
(313)-717-8818

Kristofer Karlsson

unread,
May 20, 2010, 9:36:53 AM5/20/10
to moc...@googlegroups.com
How about:
try {
   verify(mock).a();
} catch (...) {
   verify(mock).b();

Maciej Biłas

unread,
May 20, 2010, 9:17:15 AM5/20/10
to moc...@googlegroups.com
Hi Szczepan,

I'm trying to sketch an API proposal for this... sorry for the pseudo-code

import static complex.verification.Goodies.*;

interface Foo {
void a();
void b();
void c();
}

Foo foo = mock(Foo.class);

verifyComplexInteraction(or(and(foo.a(), foo.c()), foo.b()));

As I don't know the internals I would like to ask whether something
like the above is possible at all in Mockito?

To be perfectly clear: I don't want you implementing this. :-) Helping
out with drafting some sort of API would be appreciated, though. If in
the end it's not too complex to implement I can try implementing it.


Best wishes,
Maciej

On Thu, May 20, 2010 at 2:59 PM, szczepiq <szcz...@gmail.com> wrote:

Maciej Biłas

unread,
May 20, 2010, 9:51:14 AM5/20/10
to moc...@googlegroups.com
@Rajesh my question is general, I'm not assuming anything else about
the system expect for what is given

@Kristofer thanks! although /hacky/, it's already a solution. Not a
perfect one, though.

m.

Kristofer Karlsson

unread,
May 20, 2010, 10:00:18 AM5/20/10
to moc...@googlegroups.com
I think a reasonable API would be something like this:

ComplexVerifier verifier = Mockito.newComplexVerifier();

verifier.push(mock).a();
verifier.push(mock).b();
verifier.popAnd(2); // replaces a and b on the stack with and(a, b)
verifier.push(mock).c();
verifier.popOr(2); // replaces and(a, b) and c on the stack with or(and(a, b), c)
verifier.verify();

It's an interesting idea!
I may write a proof of concept for it in Mockachino.

szczepiq

unread,
May 20, 2010, 10:25:42 AM5/20/10
to moc...@googlegroups.com
>To be perfectly clear: I don't want you implementing this. :-)

ufffff


>Helping out with drafting some sort of API would be appreciated, though.

It does not look as a use case for.... reasonable code. I'm almost worried to ask you to provide real use case :D Please refactor your design to ease testing.

The api you suggested is impossible because compiler would complain about void methods. Try again :)

Cheers,
Szczepan

Max

unread,
May 20, 2010, 11:21:45 AM5/20/10
to moc...@googlegroups.com
> As I don't know the internals I would like to ask whether something like the above is possible at all in Mockito?

@Marciej, are you saying you don't know the internals of the class you're testing or the internals of Mockito?

As Szczepan said, it's a scary use case as you're not sure what the excepted behaviour is. I would consider a different use case if I were you.

James Carr

unread,
May 20, 2010, 11:59:42 AM5/20/10
to moc...@googlegroups.com
Yeah, I'd definitely vote no on this feature... you shouldn't be in a
situation where either one method or another would be invoked. I've
been in situations where something different might based on a
randomized aspect (for example, as a code kata I coded a bot that
played blackjack and made decisions to hit or stand based on his card
values and the dealer's visible card value) in which case you want to
isolate that randomization and have a clean interface you can then
stub and inject to cause the expected interactions to happen.

HTH,
James

Maciej Biłas

unread,
May 20, 2010, 12:16:53 PM5/20/10
to moc...@googlegroups.com
Please correct me if any of my assumptions about unit testing are wrong.

One example scenario that comes to my mind: You have an external HTTP
Client module that has these two methods:

Response sendRequest(HttpMethod, Data)
Response post(Data)
// which is a shorthand for sendRequest(HttpMethod.POST, Data)

// get, put, delete and others are not interesting for us at the moment

I would like to know whether a POST request is being sent to the
server as part of the method you're testing.

You have only one choice: go to the source code and see which of the
two methods the programmer used (not TDD-friendly).

I think that is a valid use case for the mechanism I'm proposing.

Best wishes,
Maciej

szczepiq

unread,
May 20, 2010, 3:16:04 PM5/20/10
to moc...@googlegroups.com
Hey,


>Please correct me if any of my assumptions about unit testing are wrong.

No problem, however I don't really understand your use case with POST. I think it's best if you show as some code that pushed you to pursue such interesting feature (use pastebin.com and trim down the code a little bit so that it is easy, yet it show real-life example).

James is spot on with his example on randomization logic. Essentially in unit testing we are trying to make the code predictable so that we can easily test it. We achieve better predictability when we replace certain dependencies with mocks. We do have full control of those mocks. Deterministic test enhances maintainability & readability.

Cheers,
Szczepan

Kristofer Karlsson

unread,
May 20, 2010, 3:22:00 PM5/20/10
to moc...@googlegroups.com
I for one think it could be useful to use Mockito for more test categories than just unit tests.
Performance tests, stress tests, scenario tests, et.c. all come to mind where some partial mocking may be desired, or using real objects with spies attached.

In such cases there might be desirable to allow for some non-determinism but still run some verifications.

It can also be noted that Mockito already supports verify(mock).foo(or(eq("hello"), eq("world")));
Doesn't that encourage the same kind of undeterministic tests?

2010/5/20 szczepiq <szcz...@gmail.com>

szczepiq

unread,
May 20, 2010, 5:14:49 PM5/20/10
to moc...@googlegroups.com
>I for one think it could be useful to use Mockito for more test categories than just unit tests.
>Performance tests, stress tests, scenario tests, et.c. all come to mind where some partial mocking may be desired, or using real objects with spies attached.

>In such cases there might be desirable tallow o for some non-determinism but still run some verifications.

Yeah, I agree. We're not saying Mockito is only for unit tests. We're just giving feedback about the feature suggested. Usually, we are not too excited about new features until we see some real code that proves it is useful.


>It can also be noted that Mockito already supports verify(mock).foo(or(eq("hello"), eq("world")));

Agreed, or() is weak and I will not put it in Mockito if I ever write it again :)

Cheers,
Szczepan

2010/5/20 Kristofer Karlsson <kristofer...@gmail.com>
I for one think it could be useful to use Mockito for more test categories than just unit tests.
Performance tests, stress tests, scenario tests, et.c. all come to mind where some partial mocking may be desired, or using real objects with spies attached.

In such cases there might be desirable tallow o for some non-determinism but still run some verifications.

Brian

unread,
May 21, 2010, 10:40:14 AM5/21/10
to mockito
Here is an example:

In OSGi, there is an interface called Bundle[1]. On the interface,
there are two methods for starting the bundle:

- public void start(int options) throws BundleException;
- public void start() throws BundleException;

Calling start(0) is equivalent to calling start(). Why should my test
say that one is correct and the other is not? In this case, I think it
is proper to verify either start() or start(0).

-Brian

[1] http://www.osgi.org/javadoc/r4v42/org/osgi/framework/Bundle.html
> > On Thu, May 20, 2010 at 5:59 PM, James Carr <james.r.c...@gmail.com>
> > wrote:
> > > Yeah, I'd definitely vote no on this feature... you shouldn't be in a
> > > situation where either one method or another would be invoked. I've
> > > been in situations where something different might based on a
> > > randomized aspect (for example, as a code kata I coded a bot that
> > > played blackjack and made decisions to hit or stand based on his card
> > > values and the dealer's visible card value) in which case you want to
> > > isolate that randomization and have a clean interface you can then
> > > stub and inject to cause the expected interactions to happen.
>
> > > HTH,
> > > James
>
> > >>> >> mockito+u...@googlegroups.com<mockito%2Bunsu...@googlegroups.com>
> > .
> > >>> >> For more options, visit this group at
> > >>> >>http://groups.google.com/group/mockito?hl=en.
>
> > >>> > --
> > >>> > You received this message because you are subscribed to the Google
> > >>> > Groups
> > >>> > "mockito" group.
> > >>> > To post to this group, send email to moc...@googlegroups.com.
> > >>> > To unsubscribe from this group, send email to
> > >>> > mockito+u...@googlegroups.com<mockito%2Bunsu...@googlegroups.com>
> > .
> > >>> > For more options, visit this group at
> > >>> >http://groups.google.com/group/mockito?hl=en.
>
> > >>> --
> > >>> Maciej Biłas
>
> > >>> --
> > >>> You received this message because you are subscribed to the Google
> > Groups
> > >>> "mockito" group.
> > >>> To post to this group, send email to moc...@googlegroups.com.
> > >>> To unsubscribe from this group, send email to
> > >>> mockito+u...@googlegroups.com<mockito%2Bunsu...@googlegroups.com>
> > .
> > >>> For more options, visit this group at
> > >>>http://groups.google.com/group/mockito?hl=en.
>
> > >> --
> > >> You received this message because you are subscribed to the Google
> > Groups
> > >> "mockito" group.
> > >> To post to this group, send email to moc...@googlegroups.com.
> > >> To unsubscribe from this group, send email to
> > >> mockito+u...@googlegroups.com<mockito%2Bunsu...@googlegroups.com>
> > .
> > >> For more options, visit this group at
> > >>http://groups.google.com/group/mockito?hl=en.
>
> > > --
> > > You received this message because you are subscribed to the Google Groups
> > "mockito" group.
> > > To post to this group, send email to moc...@googlegroups.com.
> > > To unsubscribe from this group, send email to
> > mockito+u...@googlegroups.com<mockito%2Bunsu...@googlegroups.com>
> > .
> > > For more options, visit this group at
> >http://groups.google.com/group/mockito?hl=en.
>
> > --
> > Maciej Biłas
>
> > --
> > You received this message because you are subscribed to the Google Groups
> > "mockito" group.
> > To post to this group, send email to moc...@googlegroups.com.
> > To unsubscribe from this group, send email to
> > mockito+u...@googlegroups.com<mockito%2Bunsu...@googlegroups.com>
> > .
> > For more options, visit this group at
> >http://groups.google.com/group/mockito?hl=en.
>
> --
> You received this message because you are subscribed to the Google Groups "mockito" group.
> To post to this group, send email to moc...@googlegroups.com.
> To unsubscribe from this group, send email to mockito+u...@googlegroups.com.
> For more options, visit this group athttp://groups.google.com/group/mockito?hl=en.

Max

unread,
May 21, 2010, 1:55:42 PM5/21/10
to moc...@googlegroups.com
@Brian, you are right. If start() is only calling start(0) then you don't have to verify it. A developer has to decide if method is too simple to be tested. But if later on you add some extra bits to start() then you should add a test to cover it.

On the other hand, there could be the following scenario. Say you wrote the original code and you didn't cover start(). During maintenance some other developer may need to change the start() method and forgets to add a test because he/she is not a TDDer. ;) And introduces a bug. They run your testsuite and all tests come up green. I guess you should also take into account who you're working with.

If I'm working with people I cannot trust then I'd try to cover as much methods as possible even simple ones. But if I'm working on my own or with people I can trust then I'd only cover complex ones.

Max.

Brian Mathews

unread,
May 21, 2010, 5:36:31 PM5/21/10
to moc...@googlegroups.com
@Max

I'm not sure I follow. I wasn't talking about testing the Bundle class, I was talking about testing a class that uses a Bundle. 

I am just saying that it is valid to start a Bundle using either method, and I don't think my test should limit the options for the code I am testing.


On Fri, May 21, 2010 at 12:55 PM, Max <maxo...@gmail.com> wrote:
@Brian, you are right. If start() is only calling start(0) then you don't have to verify it. A developer has to decide if method is too simple to be tested. But if later on you add some extra bits to start() then you should add a test to cover it.

On the other hand, there could be the following scenario. Say you wrote the original code and you didn't cover start(). During maintenance some other developer may need to change the start() method and forgets to add a test because he/she is not a TDDer. ;) And introduces a bug. They run your testsuite and all tests come up green. I guess you should also take into account who you're working with.

If I'm working with people I cannot trust then I'd try to cover as much methods as possible even simple ones. But if I'm working on my own or with people I can trust then I'd only cover complex ones.

Max.

Max

unread,
May 21, 2010, 6:01:28 PM5/21/10
to moc...@googlegroups.com
Oh, I see what you mean. I thought you were talking about testing in general.

szczepiq

unread,
May 22, 2010, 7:11:45 AM5/22/10
to moc...@googlegroups.com
Hey guys,


>I was talking about testing a class that uses a Bundle

If start() is equivalent to start(0) then you can solve it with start(anyInt()).

The Bundle example you presented - is it real example from your code? How did you test it then?


>I don't think my test should limit the options for the code I am testing

You mean the test should not dictate how to write the code? Unfortunately it does and always will. Bad code is hard to test. You can test bad code and complicate your tests. Or you can produce good code that is easy to test. If you care about readability, maintainability of your tests you have write code... differently.

Cheers,
Szczepan

Brian Mathews

unread,
May 24, 2010, 11:01:33 AM5/24/10
to moc...@googlegroups.com
> If start() is equivalent to start(0) then you can solve it with start(anyInt()).

What I was saying is that my code should be free to call start() or start(0) since both are valid. If I call verify(mock).start(anyInt()), it fails if I call start() in my code.


> The Bundle example you presented - is it real example from your code? How did you test it then?

No, but I have had similar situations. I ended up just picking one of the methods in my test, so my code did not have the freedom to choose. I feel like this is more fragile than it needs to be, since a non-passive change to my code ends up breaking my test.


> You mean the test should not dictate how to write the code? Unfortunately it does and always will. Bad code is hard to test. You can test bad code and complicate your tests. Or you can produce good code that is easy to test. If you care about readability, maintainability of your tests you have write code... differently.

I completely agree, but I don't think that is what is going on in this case. In this case, it is not a question of design. I just want my code to be able to take advantage of a convenience method, without having to change my test.

After thinking about it a little bit, this situation could actually be solved with the suggestion to use states: http://groups.google.com/group/mockito/browse_thread/thread/088cf0de41ed0fdc

-Brian

szczepiq

unread,
May 24, 2010, 11:33:28 AM5/24/10
to moc...@googlegroups.com
>No, but I have had similar situations. I ended up just picking one of the methods in my test, so my code did not have the freedom to choose. I feel like this is more fragile than it needs to be, since a non-passive change to my code ends up breaking my test.

I see your point. The problem is that there is no good interface to implement it java (unless you guys have some groundbreaking ideas). For example, in python, you could do: verify(mock.foo(), or(), mock.bar()); In java - have a look at interface proposed earlier in the thread (Kristofer Karlsson suggested something implementable).


>After thinking about it a little bit, this situation could actually be solved with the suggestion to use states: http://groups.google.com/group/mockito/browse_thread/thread/088cf0de41ed0fdc

Not sure how states would be helpful in this case.

Cheers,
Szczepan

James Carr

unread,
May 24, 2010, 11:45:43 AM5/24/10
to moc...@googlegroups.com
I think maybe this is an example where you shouldn't mock 3rd party
libraries? You're right... with public APIs there's often multiple
ways to accomplish something and I don't want to tie myself down to
the implementation details. Whenevr I need to use a 3rd party API to
accomplish something, I test drive the SUT with the cluster of objects
it depends on, then stub/mock this out throughout the rest of my
tests. This tends to be less brittle imho.


Thanks,
James

Brian Mathews

unread,
May 24, 2010, 12:29:14 PM5/24/10
to moc...@googlegroups.com
> Not sure how states would be helpful in this case.

I'm thinking something like this:

when(mock.start()).setStateTo("started");
when(mock.start(0)).setStateTo("started");

mock.doOperation();

verifyState(is("started"));

Brian Mathews

unread,
May 24, 2010, 12:30:26 PM5/24/10
to moc...@googlegroups.com
Sorry, had a typo:


when(mock.start()).setStateTo("started");
when(mock.start(0)).setStateTo("started");

myObject.doOperation();

verifyState(is("started"));

Kristofer Karlsson

unread,
May 24, 2010, 2:43:29 PM5/24/10
to moc...@googlegroups.com
I have a new approach of implementation (actually tested this and it seems to work), but it's not finalized

        @Test
        public void testUnion() {
                List mock = mock(List.class);

                mock.add("Hello");
                mock.remove("Hello");

                Alias a = newAlias();
                a.bind(mock).add("Hello");

                Alias b = newAlias();
                b.bind(mock).remove("Hello");

                Alias union = a.union(b);
                assertEquals(2, union.getMatches().size());
        }

Basically, the idea is to create an alias for a specific mock and method, and you can get a list of invocations for an alias at any time. You could also combine aliases, like in the example where you get the union of matching invocations.

Verifying is then just a matter of checking the size of the matches.

Brian Mathews

unread,
May 24, 2010, 3:17:12 PM5/24/10
to moc...@googlegroups.com
Is something like this possible?

        @Test
        public void testInvocations() {
                Bundle mock = mock(Bundle.class);

                //call either start method

                Invocations invocations = emptyInvocations();

                invocations.add(mock).start();
                invocations.or();
                invocations.add(mock).start(0);

                invocations.verify();
        }

-Brian

szczepiq

unread,
May 24, 2010, 3:21:33 PM5/24/10
to moc...@googlegroups.com
Oh, I get it now.

@Brian, would you really choose this:


when(mock.start()).setStateTo("started");
when(mock.start(0)).setStateTo("started");

verifyState(is("started"));

over:

verify(mock).start();

?

If your answer is yes then you can already implement it :D

when(mock.start()).thenAnswer(setStateTo("started"));
verifyState(is("started"));

You can create class (or base class) that has setStateTo(), verifyState() methods and so on. You can play with it, use it in your tests and get back if it improved the quality of your tests.

Cheers,
Szczepan

szczepiq

unread,
May 24, 2010, 3:22:08 PM5/24/10
to moc...@googlegroups.com
yes, it is possible.

Maciej Biłas

unread,
May 24, 2010, 3:48:29 PM5/24/10
to moc...@googlegroups.com
From what I've been able to catch up with the discussion the states
approach does is not an elegant enough solution for the problem. Let
me get back to my example from a couple of posts ago:

You have an external HTTP. Client module that has these two methods:
sendRequest(HttpMethod, Data) : Response
post(Data) : Response
// which is a shorthand for sendRequest(HttpMethod.POST, Data)

now I would like to verify that exactly three POST requests where
send. No more, no less, three shall be the number of requests and the
number of requests shall be three... [1]

If it is possible to accomplish at all this would mean that I'd have
to set three states, say "POST-1", "POST-2", "POST-3"... doesn't seem
right to me.

@Kristoffer is the approach you showed available as actual software?
Can I grab the source? It looks quite promising.

Having a cleaner syntax for matching the number of interactions would
be nice. This is not the best:
assertEquals(2, union.getMatches().size());

[1] http://www.youtube.com/watch?v=xOrgLj9lOwk

Cheers,
Maciej
--
Maciej Biłas

Kristofer Karlsson

unread,
May 24, 2010, 4:30:16 PM5/24/10
to moc...@googlegroups.com
Yes, it's real software, but under development, and it's not integrated with Mockito unfortunately.
Here's the download link http://code.google.com/p/mockachino/downloads/list
and here is a simple usage example
http://code.google.com/p/mockachino/source/browse/trunk/test/blackbox/se/mockachino/AliasTest.java

I'm not done experimenting so don't take it too seriously :)


On Mon, May 24, 2010 at 9:48 PM, Maciej Biłas <mac...@inszy.org> wrote:

@Kristoffer is the approach you showed available as actual software?
Can I grab the source? It looks quite promising.

Having a cleaner syntax for matching the number of interactions would
be nice. This is not the best:
assertEquals(2, union.getMatches().size());

[1] http://www.youtube.com/watch?v=xOrgLj9lOwk

Cheers,
Maciej


--
Maciej Biłas

--
You received this message because you are subscribed to the Google Groups "mockito" group.
To post to this group, send email to moc...@googlegroups.com.
To unsubscribe from this group, send email to mockito+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/mockito?hl=en.

szczepiq

unread,
May 25, 2010, 3:17:40 PM5/25/10
to moc...@googlegroups.com
To summarize this thread:

1. Nobody provided a real use case for the feature in question. We believe that convincing use case is a requirement for designing decent APIs
2. Looking at the APIs suggested by users: it feels the feature leads to less readable and therefore harder to maintain tests. Hand-rolled mock could offer significantly better readability.
3. Even if the feature might be useful in some edge cases the benefit of "relaxed method" verification is shadowed by complication to the test code. Also, "relaxed method" verification can still break when the user calls yet a different method, that is not yet declared as a viable interaction.
4. Exemplary use cases provided by users seem float around mocking 3rd party types. Mocking types we don't own is an anti pattern that points out the lack of thin layer around the 3rd party libs we use.

That's why I'm not very excited about this feature. However if someone implements it and finds out that it is useful for him, please share with us!

Peace,
Szczepan
=)

gradi

unread,
Jun 5, 2010, 3:09:11 PM6/5/10
to mockito
Hi Everybody,

I think I would have an example for the feature in question.

I am currently trying to mock an interface to a persistent object. The
interface defines setters and getters for all attributes, but it gives
as well two generic methods get() and set() which take the attribute
name as the additional argument.

interface IObject {
Object getA();
setA(Object a);
Object getB();
setB(Object b);
...

get(String name);
set(String name, Object o);
}

The class under test uses that interface. The implementation detail,
which getter (specific or generic one) is actually used, is in fact
irrelevant.

Greetings
Gradi

szczepiq

unread,
Jun 7, 2010, 5:42:11 AM6/7/10
to moc...@googlegroups.com
It could be an excellent example... if only mocking getters & setters was not a well known anti pattern ;)

Anyway, if you like the idea you can implement it and try using in your tests. If you find it useful for your testing efforts please share this experience with us.

Cheers,
Szczepan

Geo

unread,
Oct 29, 2013, 7:48:33 PM10/29/13
to moc...@googlegroups.com
1. Nobody provided a real use case for the feature in question. We believe that convincing use case is a requirement for designing decent APIs

I have a use case that's been bothering me for a while. Perhaps it is convincing. Consider this little example:

RefactorListener listener = mock(RefactorListener.class);
Refactorer testMe = new Refactorer("void main() { doIt(); } void doIt() { cout << "Hello World"; }");
testMe.rename("doIt", "printHello");
InOrder inOrder = inOrder(listener);
inOrder.verify(listener).codeReplaced(testMe, 14, 24. "doIt");
inOrder.verify(listener).codeReplaced(testMe, 35, 45, "doIt");

The idea is that testMe changes the name of the doIt function in the source code and reports each change to listener as it happens. Unfortunately I am overspecifying this test. I don't want to verify which order the instances of "doIt" get replaced, but some of the arguments to "codeReplaced" need to change if the two calls are in the opposite order, like this:
inOrder.verify(listener).codeReplaced(testMe, 29, 39. "doIt"); // This one is different, shifted 6 characters to the left because it happens first instead of second
inOrder.verify(listener).codeReplaced(testMe, 14, 24, "doIt");

So I wouldn't be verifying the correct arguments if I didn't also verify the order. I would like to provide for both alternatives in the test so that the system being tested isn't forced to sort the changes it makes.
 
2. Looking at the APIs suggested by users: it feels the feature leads to less readable and therefore harder to maintain tests. Hand-rolled mock could offer significantly better readability.

Personally, I really like Kristofer's way of doing it. I would love to be able to do things like this:
inOrder.push(listener).codeReplaced(testMe, 14, 24. "doIt");
inOrder.push(listener).codeReplaced(testMe, 35, 45, "doIt");
inOrder.popAnd(2);
inOrder.push(listener).codeReplaced(testMe, 29, 39. "doIt");
inOrder.push(listener).codeReplaced(testMe, 14, 24, "doIt");
inOrder.popAnd(2);
inOrder.popOr(2);
inOrder.verify();

David Wallace

unread,
Oct 30, 2013, 6:04:59 AM10/30/13
to moc...@googlegroups.com
This feels to me like a good use of an argument captor.  Do your logic outside of your verification.


--
You received this message because you are subscribed to the Google Groups "mockito" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mockito+u...@googlegroups.com.

To post to this group, send email to moc...@googlegroups.com.

Geo

unread,
Oct 30, 2013, 8:03:32 PM10/30/13
to moc...@googlegroups.com
On Wednesday, October 30, 2013 3:04:59 AM UTC-7, David Wallace wrote:
This feels to me like a good use of an argument captor.  Do your logic outside of your verification.

That's a clever solution. Thank you. Unfortunately it only works in this case because there's only one method being called. It wouldn't work in general. For example, if  the listener had no "replace" method and instead treated deleting code and inserting code as separate operations, then argument captors wouldn't be able to tell me in what order the various inserts and deletes happened.

Brice Dutheil

unread,
Nov 4, 2013, 12:28:35 PM11/4/13
to moc...@googlegroups.com
It's an interesting API, but I feel this proposition too complicated especially with the popAnd, etc.

You can still write your own verifier, and see the result (API wise) and report what you've found ;)


-- Brice


--

Geo

unread,
Nov 4, 2013, 11:58:50 PM11/4/13
to moc...@googlegroups.com
It's an interesting API, but I feel this proposition too complicated especially with the popAnd, etc.

Here's another API to consider. Let there be an Option class that has two subclasses: InOrderOption and UnorderedOption. UnorderedOption has the full usual set of "verify" methods, and InOrderOption has all the methods of InOrder, but instead of verifying they only record the verifications for possible future use. Option would have a "verifyOneOf" method that would take a list or an array of Options and record that at least one of them should successfully verify for this Option to successfully verify, and a "verifyAllOf" method which does the same thing except all the given Options must verify. Then Mockito could have static verifyOneOf and verifyAllOf to actually do the verifications.

This API would also make it possible to put unordered verifications into a sequence of InOrder verifications if InOrder had a method to verify an UnorderedOption.

Tom De Greyt

unread,
Feb 7, 2014, 9:26:02 AM2/7/14
to moc...@googlegroups.com
Let's say I have defined in my project these interfaces :

public interface Topic {

    /**
     * this must be equivalent to message(payload.getBytes())
     */
    void message(String payload);

    void message(byte[] payload);

}

public interface TopicClient {

    /**
     * postcondition : the message "COMPLETE" has been sent to the Topic.
     */
    void doSomething();

}

I want to make a test that tests whether implementations of TopicClient honor the contract.

public abstract class AbstractTopicClientTest {

    protected abstract TopicClient getInstanceToTest(Topic topic);

    @Test
    public void testCompletedIsSentToTopic() {
        final Topic topic = mock(Topic.class);
        TopicClient topicClient = getInstanceToTest(topic);

        topicClient.doSomething();

        verify(topic).message("COMPLETED".getBytes());
    }

}

Implementations that use the message(String) method will not pass this test.

How to do this? Simply stub the topic so that calls to message(String) are indeed equivalent to calls to method message(byte[])

public abstract class AbstractTopicClientTest {

    protected abstract TopicClient getInstanceToTest(Topic topic);

    @Test
    public void testCompletedIsSentToTopic() {
        final Topic topic = mock(Topic.class);
        doAnswer(new Answer<Void>() {
            @Override
            public Void answer(InvocationOnMock invocation) throws Throwable {
                topic.message(((String) invocation.getArguments()[0]).getBytes());
                return null;
            }
        }).when(topic).message(anyString());
        TopicClient topicClient = getInstanceToTest(topic);

        topicClient.doSomething();

        verify(topic).message("COMPLETED".getBytes());
    }

}

KARR, DAVID

unread,
Feb 7, 2014, 10:03:41 AM2/7/14
to moc...@googlegroups.com

I’ll let someone else answer whether it’s possible to do this with Mockito (perhaps PowerMockito).  It sounds doubtful to me.

 

However, this is something that is possible to do with PMD.  The API gives you access to the AST of a class, and this scenario you describe is something that could be verified with that API.

 

--

Reply all
Reply to author
Forward
0 new messages