In unit testing often we run a lot of related tests sequentialy.
In my case I'm testing a component that receives its dependencies in
the constructor.
I create a mock, setup some stubbing, and then construct the component
I want to test passing the mock as a parameter. And I'd like doing
that just once for a whole set of related tests (all tests in my test
class, for instance).
If all I wanted to do was stubing, it would work nicely. But if I also
want to do verification I will have problems because the mock will
accumulate the interactions since its creation.
Is there any way to "clear" the interaction records on a mock? So in
each test method I could simply "clear-run-verify", without the need
to recreate the mock and (because of the constructor dependency
injection pattern) create other target component instance.
Regards,
--
Pedro Pedruzzi | V2COM
Do you have any code snippet, which actually requires clear/reset on the mock ?
You can create a mock and other target components in @Before method,
which is invoked before each test method, that way you will have fresh
mock for each test.
Beside, when using Mockito, you can verify what you have interest in
even if more invocations happen, unless you call
Mockito.verifyNoMoreInteractions() at the end of each test.
Hopes it helps.
Igor
Take the following snippet as an example (it uses TestNG):
public class TimedCacheTest {
private final Object KEY = new Object();
private final Object VALUE = new Object();
private final Object NEW_VALUE = new Object();
private ObjectLoader mockLoader;
private TimedCache cache;
@BeforeClass
public void setup() {
// ObjectLoader mock
mockLoader = mock(ObjectLoader.class);
// consecutively stubbing (mockito 1.4 or higher)
stub(mockLoader.load(KEY)).toReturn(VALUE).toReturn(NEW_VALUE);
// suppose this TimeCache construction is somehow a time expensive task
// in a way I want to do it only once
cache = new TimedCache(mockLoader, mockClock, mockReloadPolicy);
}
@BeforeMethod
public void setup() {
// if I could just
clear(mockLoader);
// I will do not have to reinstanciate the mock and the TimeCache
// nor redefining the "global" stubbings
}
@Test
public void testFirstLookUp() {
assertSame(VALUE, cache.lookUp(KEY));
verify(mockLoader).load(KEY);
}}
@Test
public void testCachedObject() {
assertSame(VALUE, cache.lookUp(KEY));
assertSame(VALUE, cache.lookUp(KEY));
verify(mockLoader).load(KEY);
}
@Test
public void testCacheReload() {
assertSame(VALUE, cache.lookUp(KEY));
delay(2000);
assertSame(NEW_VALUE, cache.lookUp(KEY));
verify(mockLoader, times(2)).load(KEY);
}
// ...
}
Pedro Pedruzzi
But is it a real scenario you have there?
Firstly, I don't think there is much to gain when using @BeforeClass
(miliseconds? did anyone measure it?). Secondly, one of the key points
of mocking is the ability to replace expensive logic with a cheap but
controllable substitute. If there is something expensive in TimedCache
creation then this is something that should be encapsulated in a
dependency and mocked out.
Here is my test:
@BeforeMethod
public void setup() {
mockLoader = mock(ObjectLoader.class);
cache = new TimedCache(mockLoader, otherStuff);
}
@Test
public void shouldReadValueFromCache() {
//I prefer to stub per test method:
stub(mockLoader.load("foo")).toReturn("bar");
assertSame("bar", cache.lookUp("foo"));
assertSame("bar", cache.lookUp("foo"));
verify(mockLoader, once()).load("foo");
}
@Test
public void shouldReloadValue() {
stub(mockLoader.load("foo")
.toReturn("bar")
.toReturn("baz");
assertSame("bar", cache.lookUp("foo"));
delay(2000);
assertSame("baz", cache.lookUp("foo"));
//don't really need verify() here
}
I prefer using just @BeforeMethod. That makes me happier because there
is no state left over after a test method. I guess it makes the test
methods truly independent and maintainable. Actually I don't remember
ever using @BeforeClass. I don't even know what is (and if there is)
the junit4 equivalent (and I'm a junit user :) ...
What do you think?
Cheers,
Szczepan Faber
Thanks for your response.
On Wed, Jul 2, 2008 at 8:32 PM, szczepiq <szcz...@gmail.com> wrote:
>
> I agree that when object creation is expensive then the natural tweak
> would be using @BeforeClass instead of just @BeforeTest. The class
> under test is created once instead n times, where n is the number of
> tests.
That is my point.
> But is it a real scenario you have there?
It is not. But I think it is completely possible.
In fact I think I was making a wrong assumption about testing methods.
Your point that tests methods should be independent made sense to me.
I don't see it as a general rule. TestNG for example has a mechanism
of test dependencies. But I think this is just about prerequisites
(skip the dependent test if "parent" test failed avoid failing a whole
set of tests - it is a very handy feature of TestHG by the way).
I was trying to make a statefull test class. I don't know if this
makes sense or is completely wrong. I just feel that it is not the
best practice.
I will make my test classes stateless as you suggest. Let us see if I
get more happy with that! :-)
Thanks for your time and for the excellent mocking framework.
Regards,
--
Pedro Pedruzzi | V2COM
PS: I am using mockito 1.4, and I'm waiting to see it on maven official repo!
This is true. For example:
verify(foo, times(2)).bar();
is equal to:
inOrder.verify(foo).bar();
inOrder.verify(foo).bar();
Obviously I recommend using inOrder only if it is relevant to test
interactions in order :)
Cheers,
Szczepan Faber
When you do this:
_observable.send(message);
there is only single interaction:
observer.send(observed, message);
So in the test:
...
order.verify(mockObserver).send(_observed, message);
verifyNoMoreInteractions(mockObserver);
order.verify(mockObserver).send(_observed, message); // will fail
because inOrder does not accumulate.
Now the response for the other question about reset()
>now want to verify that fileDeleted() is called on the listener,
>ignoring whatever happened before.
If you're ignoring whatever happened before then why do you use
verifyNoMoreInteractions() ? verifyNoMoreInteractions() is rather
recommended for those situations where you actually don't want to
ignore anything.
There is a common misuse of verifyNoMoreInteractions() that I often
see. Devs who did a lot of mocking with expect-run-verify libraries
tend to write verifyNoMoreInteractions() very often or even in every
test method. verifyNoMoreInteractions() is not a part of the mockito
contract that should be called per test method. See my post here:
http://groups.google.com/group/mockito/t/a7b6c7632c728e76
The very point of Mockito library is to provide painless, noninvasive
testing. In your example for instance, you "want to verify that
fileDeleted() is called on the listener, ignoring whatever happened
before". Mockito helps you to test precisely what you want: verify
that fileDeleted() is called on the listener, ignoring other
interactions that are irrelevant in your test.
So, let's get back to your example. I think there are 2 options here:
1. I could write pseudo-functional, scenario-like test where I do
multiple operations (createFile(), deleteFile(), etc.). In that kind
of test I could verify all interactions. At the end, I could put
verifyNoMoreInteractions() (though, I probably wouldn't - it depends
if it's relevant).
2. I could write classic unit test with small test methods focused
around behaviour. In that kind of test I would verify only the
interaction that is relevant to the test method (e.g.
shouldNotifyDeleteMessage(), shouldNotifyCreateMessage()).
Considering what I said above would you still use reset() method in
your example?
Hope that helps,
Szczepan Faber.
Interesting idea of using reset() functionality. I guess I can
generalize the pattern:
test {
unit.exercise();
mock.forgetInteractions();
unit.exerciseAgain();
mock.verifyInteractions();
mock.verifyNoMoreInteractions();
}
The problem is that I don't know if it is a good pattern... Cannot
really say it's bad at all times, though. Generally in unit tests, I
don't exercise the unit more than once per test method. In functional
tests I don't generally use mocks. In most tests I don't generally use
verifyNoMoreInteractions() and so on.
Your scenario could be a legitimate use of reset(). OTOH, introducing
reset() functionality opens the framework for bad usage with lengthy
tests with exercise->verify->reset->exercise->... sequences (I'm 100%
sure some devs will do that). Also, verifyNoMoreInteractions() is a
message telling that all interactions are specified in *this* test.
That's why I'd rather not enable mock resetting (unless I'm voted out
by users. Any votes now?). But I will keep your idea in mind.
Also, I'm not entirely convinced why you cannot just do the following
(show me the code under test to prove that verifyNoMoreInteractions()
is required :)
test {
unit.exercise();
unit.exerciseAgain();
mock.verifyInteractions();
}
Cheers,
Szczepan Faber
It maybe a little bit of topic, but I have a strong feeling that
Monitor object keeps the state from the moment it's created, whereas
the test tries to verify only part of the state.
Maybe the following code modification would solve your problem,
without a need for reset functionality.
protected void setUp() throws Exception {
super.setUp();
_data = new TestData(this);
_data.clean();
_listener = mock(DirectoryMonitor.Listener.class);
_monitor = new DirectoryMonitor(new
AwkFilenameFilter(REGEX), _listener);
}
and the test case is
public void testFileDeleted() {
_data.createFile(FILE1, "hello");
_monitor.observe(_data.getRoot());
_data.deleteFile(FILE1);
_monitor.poll();
verify(_listener.getMock()).fileDeleted(_data.getFile(FILE1));
verifyNoMoreInteractions(_listener.getMock());
}
Cheers,
Igor
Let's leave the discussion what's a functional test :) I just don't
remember using mocks in functional tests - I'm more interested in
system behaviour rather than which method was called on what object.
> I think in general it is good practice to be precise in
> verifications.
or:
>How do I know that only fileDeleted was called
> after the file was deleted and no other method?
By "being precise" you mean being extra-defensive and check for
unexpected methods, right? If that's how you define precision than I
don't think it's a good practice:
http://monkeyisland.pl/2008/07/12/should-i-worry-about-the-unexpected
> In other words, there should not be a rule to avoid
> verifyNoMoreInteractions() but there really *must* be a rule to avoid
> verifying interactions that are irrelevant for the test case at hand.
I really like what you said about avoiding irrelevant interactions.
But I believe that verifyNoMoreInteractions() in most cases is
irrelevant (unless the implementation really does call different
methods that I want to exclude specifically). For example,
verifyNoMoreInteractions() can be relevant when it describes the
conditional logic
(http://groups.google.com/group/mockito/t/a7b6c7632c728e76)
> And I don't see why a reset() in test code would be bad.
Here is why. Instead of this one:
{
File testfile = testdata.createFile(file);
monitor.poll();
verify(listener).fileCreated(testfile);
testfile.delete();
reset(listener);
monitor.poll();
verify(listener).fileDeleted(testfile);
verifyNoMoreInteractions();
}
you could write:
{
File testfile = testdata.createFile(file);
monitor.poll();
verify(listener).fileCreated(testFile);
}
{
File testfile = testdata.createFile(file);
monitor.poll();
testfile.delete();
monitor.poll();
verify(listener).fileDeleted(testfile);
}
Morphing a bigger test into 2 focused tests make your suite *not worse
in quality* but better in readability and maintainability.
I have a feeling that you'd like write the test that:
- checks that delete() is called when file is deleted
- checks that only delete() is called when file is deleted
- checks that delete() is called when: the file is created and then deleted.
What's the true focus of this test? Does checking those 3 things
together make the implementation expose some exceptional scenario? Why
not just splitting it up?
For the sake of the argument, let's say it's truly important to test
all that together. So, what I would do is a handy resetMonitor()
method:
{
File testfile = testdata.createFile(file);
//file creation makes the monitor do nasty things that are irrelevant, so:
resetMonitor();
testfile.delete();
monitor.poll();
verify(listener).fileDeleted(testfile);
verifyNoMoreInteractions();
}
Hope that helps
Cheers,
Szczepan Faber
And sometimes all of those scenarios lead to less maintainable tests
that test too much.
There is no other way than looking at those on the case-by-case basis.
And this is what this mailing list stands for.
>As you can tell from the discussion with Szczepan, it is clear that he
>is against supporting this 'reset' functionality in mockito.
Hopefully you can tell from the discussion that I *just didn't find a
valid case* for reset(). So yes, I'm against controversial features
that don't really bring value (quite the opposite, actually).
>Sometimes, you just want to use a mocking framework to help
>you in implementing/improving existing tests and redesign of the code
>is not always possible (this usually occurs with commercial software).
Maybe. OTOH the willingness to refactor is a virtue I'd like to promote.
Cheers,
Szczepan Faber
>is against supporting this 'reset' functionality in mockito. The
>problem with this discussion is that it focuses on a very simple
>example which can easily be refactored. However, that is not always
>the case. Sometimes, you just want to use a mocking framework to help
>you in implementing/improving existing tests and redesign of the code
>is not always possible (this usually occurs with commercial software).
I'm not against it. I just didn't find a valid case for it.
>The only thing is that I do not want to add such
>subscription functionality since I don't need it.
You need it because your test needs it...