I can only assume the implementation of verifyInsertSync(...) method.
It would be much easier for me to help, if you reveal a little bit
internals of verifyInsertSync(...).
Thanks,
Igor
Your example is nearly what I mean, but without the second setup().
@Test public void test...() {
setup1();
someCodeThatInteractsWithMocks();
verify1(....)
verify1(....)
reset(mock1, mock2);
someMoreCodeThatInteractsWithMocks();
verify2(....)
verify2(....)
}
Maybe its just me, but I often find it more obvious to write longer
procedural tests. Particularly if you are doing something that requires
non-trivial setup, and you want to check things are OK after step 1
before going on to step2. Without reset, I may be unnaturally forced to
write:
@Test public void test1...() {
setup1();
someCodeThatInteractsWithMocks();
verify1(....)
verify1(....)
}
@Test public void test2...() {
setup1();
someCodeThatInteractsWithMocks();
someMoreCodeThatInteractsWithMocks();
verify2(....)
verify2(....)
}
which just feels wrong.
If you are looking for more concrete examples, check out some of The
Grinder tests, e.g.
http://grinder.svn.sourceforge.net/viewvc/grinder/trunk/source/tests-src/net/grinder/communication/TestMessageDispatchSender.java?view=markup
(This uses my home grown mocking framework rather than Mockito).
Finally, I also think it's similarly annoying that I can't do this:
stub(mymock.op()).toThrow(someException);
// ...
stub(mymock.op()).toReturn(blah); // Can't change behaviour - throws
// someException.
Regards,
- Phil
> <http://grinder.svn.sourceforge.net/viewvc/grinder/trunk/source/tests-src/net/grinder/testutility/RandomStubFactory.java?view=markup>
> if you are interested).
>
>
>
Actually, you are naturally forced to split the test into two separate
ones and you naturally end up with more fine grained tests and get rid
of duplication - which is as much important as in production code.
Tests are much easier to read, understand and maintain.
Maybe the example we debate about is not the best one, however after
the split it became obvious that test1 is a subset of test2. So do you
really need both of them ?
I rather think your intention was to make assumption about
interactions, that have already taken place, before you continue to
introduce some more. Besides, you want to be sure that second method
invocation has introduced some new interactions. Apparently, verifying
all at the end wouldn't prove where interactions have happened. Is it
the intention you would like to have reset for ?
Personally form me, these are candidates for separate tests and
excessive setup is a hint that maybe design is not the best one
possible (hint not a syndrom).
Second, you may simplify it a little bit :)
@Before
public void setup() {
}
@Test public void test1...() {
someCodeThatInteractsWithMocks();
verify1(....)
verify1(....)
}
@Test public void test2...() {
someCodeThatInteractsWithMocks();
someMoreCodeThatInteractsWithMocks();
verify2(....)
verify2(....)
}
What's wrong with writing times(2) ??
What's between stub and stub ? Verification ? Execution logic ?
stub(mymock.op()).toThrow(someException);
// ... ????????????????????
stub(mymock.op()).toReturn(blah); // Can't change behaviour - throws
Cheers
Igor
Thanks for the feedback.
I'm quite willing to believe that any example I can come up with can be
reduced in this manner; and in fact I've had little trouble in working
around these issues. However, I find it annoying that the tool is taking
away my choice of how I want to structure tests. I'd rather be focussing
my refactoring time on the code under test.
(I find it particularly annoying, because otherwise Mockito is very
pretty and I've begun to care about it).
- Phil
>I'm quite willing to believe that any example I can come up with can be
>reduced in this manner;
We don't want to reduce your examples - not at all! A good example is
a main motivator to enhance the library and we are eager to do it.
Trust me, I looked at
TestMessageDispatchSender.
>and in fact I've had little trouble in working around these issues.
Missing reset() is not an issue. It's a deliberate action to promote
good testing habits and make the API simpler. I'm strongly biased in
favour of frameworks/tools that enforce good practices.
>However, I find it annoying that the tool is taking away my choice of
how I want to structure tests.
Frankly, that's the point. I think the goal of any tools (and even
practices or methodologies) is to reduce choices, leaving only good
choices. Small, focused test method is a good choice.
>I find it particularly annoying, because otherwise Mockito is very
>pretty and I've begun to care about it).
I'm sorry to disappoint you :( For me, mockito is not a mere test
tool. It's also a vision of how I see decent test code: simple, clean,
small. Long, procedural-like tests don't fit there. IMHO, Long,
scenario-like tests make sense for acceptance/functional tests where
mocks should not be used anyway.
I'm not saying NO to reset(). I've just never needed it. More over, I
used easymock for years and never used it. Whenever I saw reset() in
existing code, the test was dodgy and reset() was an attempt to
deodorize different smells in code.
Obviously, I can be wrong. That's why I'm still waiting for decent examples.
Cheers,
Szczepan Faber
Unfortunately, I won't have a chance to use Mockito in anger until I up
The Grinder to Java 5. In the meantime I'll keep my eye out for
interesting, multi-step unit tests.
I strongly suggest that a distillation of this should be in the FAQ.
Here's a quick draft:
Q. Each mock keeps a full account of all its calls. Why can't I "reset"
a mock in the middle of a test?
A. The lack of a reset method is deliberate to promote good testing
habits and to make the API simpler. Re-factor your test into a number of
smaller tests.
Q. Once I've stubbed a mock to throw an exception, how can I reset this
behaviour?
A. You can't. Once a method has been stubbed to throw an exception, it
will always throw an exception. Unfortunately there is no clean way of
implementing this due to the nature of Mockito syntax.
However, the ability to alter a stubs behaviour is rarely required.
Consider splitting your test into two smaller tests, or using two
separate mocks. If you have an example of a unit test that requires this
ability, please send details to the Mockito Google group.
- Phil
Thank you :)
> I strongly suggest that a distillation of this should be in the FAQ.
Thanks for a suggestion. I'm going to put distilled version of some
interesting threads in FAQ. Questions about restet() and alike tend to
come up very often.
Thanks,
Szczepan Faber