{"id":307,"date":"2013-12-06T22:04:46","date_gmt":"2013-12-06T21:04:46","guid":{"rendered":"http:\/\/benjiweber.co.uk\/blog\/?p=307"},"modified":"2013-12-06T22:04:46","modified_gmt":"2013-12-06T21:04:46","slug":"strictmocks-in-mockito","status":"publish","type":"post","link":"https:\/\/benjiweber.co.uk\/blog\/2013\/12\/06\/strictmocks-in-mockito\/","title":{"rendered":"StrictMocks in Mockito"},"content":{"rendered":"<p class=\"lead\">Today someone asked how to verify that only your stubbed interactions occur, and no others (when using Mockito). <\/p>\n<p>I have heard this asked this quite often, especially by people used to JMock where mocks are strict by default.<\/p>\n<p>I\u2019d be interested in knowing if there\u2019s an out of the box way of doing this.<br \/>\nThe normal way to do this is to verify all the calls you expect to happen and then verify no more interactions occur.<\/p>\n<p>This often seems like unnecessary duplication with the &#8220;when&#8221; stubbing. You end up with something like<\/p>\n<pre lang=\"java\">\r\n    @Test\r\n    public void exampleOfRedundantVerify() throws Exception {\r\n        Duck duck = mock(Duck.class);\r\n        when(duck.quack()).thenReturn(\"quack\");\r\n        when(duck.waddle()).thenReturn(\"waddle\");\r\n\r\n        duck.quack();\r\n        duck.waddle();\r\n\r\n        \/\/Why do we need to do this?\r\n        verify(duck).quack();\r\n        verify(duck).waddle();\r\n\r\n        verifyNoMoreInteractions(duck);\r\n    }\r\n<\/pre>\n<p>If you omit the two verify lines then the test will fail, despite us stubbing quack with &#8220;when&#8221;. It would be nice to remove this duplication.<\/p>\n<p>Now, at this point someone will probably point out that often verifyNoMoreInteractions, and even multiple verifications in a test can be a sign of an inflexible test that is easy to break with minor implementation changes. However, sometimes you really do want to assert that a collaborator is only used in a specific way. You might also temporarily want the mocks to be more vocal about how they are used, in order to help diagnose why a test is failing. <\/p>\n<p>So how can we make this better with Mockito? Mockito provides an <a href=\"http:\/\/mockito.googlecode.com\/svn\/branches\/1.7\/javadoc\/org\/mockito\/stubbing\/Answer.html\">Answer<\/a>.<br \/>\nTo implement Answer you simply have to implement <\/p>\n<pre lang=\"java\">\r\n    public T answer(InvocationOnMock invocation) throws Throwable\r\n<\/pre>\n<p>This is called when you invoke a method on a mock.<\/p>\n<p>Answer is an interface that Mockito provides to allow you to specify the response to a method invocation on a Mock. It gives a bit more power than simply returning a value. For instance you can <a href=\"http:\/\/benjiweber.co.uk\/blog\/2012\/11\/10\/test-stubbing-with-builders-real-objects-and-caches\/\">use it to capture method parameters passed to stubbed method calls for later assertions.<\/a><\/p>\n<p>Answer is useful for solving this problem because we can specify a default Answer that a mock will use whenever a method invocation has not been stubbed. In our case we want the test to fail, so we can simply throw an Exception with some information about the unexpected invocation.<\/p>\n<p>Here&#8217;s what we can enable<\/p>\n<pre lang=\"java\">\r\n    @Test\r\n    public void exampleStubbedAll() throws Exception {\r\n        Duck duck = strictMock(Duck.class);\r\n        when(duck.quack()).thenReturn(\"quack\");\r\n\r\n        verifyNoUnstubbedInteractions(duck);\r\n\r\n        duck.quack();\r\n    }\r\n\r\n\r\n    @Test(expected = NotStubbedException.class)\r\n    public void exampleNotStubbedAll() throws Exception {\r\n        Duck duck = strictMock(Duck.class);\r\n        when(duck.quack()).thenReturn(\"quack\");\r\n\r\n        verifyNoUnstubbedInteractions(duck);\r\n\r\n        duck.quack();\r\n        duck.waddle();\r\n    }\r\n<\/pre>\n<p>Here the first test only performs stubbed operations on the mock, so passes. The second test calls an unstubbed method and an Exception is thrown.<\/p>\n<p>How is it implemented? First we create a static method to create ourselves a mock. The second argument here is the default answer, Mockito will invoke the &#8220;answer&#8221; method on this handler for every unstubbed invocation.<\/p>\n<pre lang=\"java\">\r\n    public static <T> T strictMock(Class<T> cls) {\r\n        return Mockito.mock(cls, new StrictMockHandler());\r\n    }\r\n<\/pre>\n<p>The answer implementation simply throws an Exception, if it is in Strict mode. We need to provide a toggle for &#8220;strictness&#8221; so that our when(mock.quack()) invocation during stubbing does not cause an Exception to be thrown. I believe this is necessary without horrible hacks like looking back up the stack trace to see where it is called (Or does Mockito maintain some global state about the stubbing context?)<\/p>\n<pre lang=\"java\">\r\n    public static class StrictMockHandler implements Answer {\r\n        public boolean strict = false;\r\n\r\n        public Object answer(InvocationOnMock invocation) throws Throwable {\r\n            if (strict) throw new NotStubbedException(invocation.getMethod().getName());\r\n            return null;\r\n        }\r\n    }\r\n<\/pre>\n<p>Finally, we provide a static method for toggling the strictness after our stubbings, this pulls out the default Answer from the mock using a utility that Mockito provides.<\/p>\n<pre lang=\"java\">\r\n    public static void verifyNoUnstubbedInteractions(Object mock) {\r\n        StrictMockHandler handler = ((StrictMockHandler) new MockUtil().getMockHandler(mock).getMockSettings().getDefaultAnswer());\r\n        handler.strict = true;\r\n    }\r\n<\/pre>\n<p>I don&#8217;t believe this can deasily work with @Mock annotation based mock creation. You can pass in a different answer by doing @Mock(answer=Answers.RETURNS_SMART_NULLS), but this is limited to the values on the <a href=\"http:\/\/docs.mockito.googlecode.com\/hg\/latest\/org\/mockito\/Answers.html\">Answers enum.<\/a><\/p>\n<p>To do this with annotations I think you&#8217;d have to create a JUnit @Rule or Runner that handles a new annotation, maybe @StrictMock instead of @Mock <\/p>\n<p>See the <a href=\"https:\/\/github.com\/benjiman\/test-examples\/blob\/master\/src\/main\/java\/uk\/co\/benjiweber\/mockito\/MockUtils.java\">implementation<\/a> and <a href=\"https:\/\/github.com\/benjiman\/test-examples\/blob\/master\/src\/test\/java\/uk\/co\/benjiweber\/testexamples\/StrictMockExampleTest.java\">sample tests<\/a> on github.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today someone asked how to verify that only your stubbed interactions occur, and no others (when using Mockito). I have heard this asked this quite often, especially by people used to JMock where mocks are strict by default. I\u2019d be interested in knowing if there\u2019s an out of the box way of doing this. The&#8230;  <a href=\"https:\/\/benjiweber.co.uk\/blog\/2013\/12\/06\/strictmocks-in-mockito\/\" class=\"more-link\" title=\"Read StrictMocks in Mockito\">Read more &raquo;<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[8],"tags":[23,19],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v14.9 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/benjiweber.co.uk\/blog\/2013\/12\/06\/strictmocks-in-mockito\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"StrictMocks in Mockito - Benji&#039;s Blog\" \/>\n<meta property=\"og:description\" content=\"Today someone asked how to verify that only your stubbed interactions occur, and no others (when using Mockito). I have heard this asked this quite often, especially by people used to JMock where mocks are strict by default. I\u2019d be interested in knowing if there\u2019s an out of the box way of doing this. The... Read more &raquo;\" \/>\n<meta property=\"og:url\" content=\"https:\/\/benjiweber.co.uk\/blog\/2013\/12\/06\/strictmocks-in-mockito\/\" \/>\n<meta property=\"og:site_name\" content=\"Benji&#039;s Blog\" \/>\n<meta property=\"article:published_time\" content=\"2013-12-06T21:04:46+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebSite\",\"@id\":\"https:\/\/benjiweber.co.uk\/blog\/#website\",\"url\":\"https:\/\/benjiweber.co.uk\/blog\/\",\"name\":\"Benji&#039;s Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":\"https:\/\/benjiweber.co.uk\/blog\/?s={search_term_string}\",\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/benjiweber.co.uk\/blog\/2013\/12\/06\/strictmocks-in-mockito\/#webpage\",\"url\":\"https:\/\/benjiweber.co.uk\/blog\/2013\/12\/06\/strictmocks-in-mockito\/\",\"name\":\"StrictMocks in Mockito - Benji&#039;s Blog\",\"isPartOf\":{\"@id\":\"https:\/\/benjiweber.co.uk\/blog\/#website\"},\"datePublished\":\"2013-12-06T21:04:46+00:00\",\"dateModified\":\"2013-12-06T21:04:46+00:00\",\"author\":{\"@id\":\"https:\/\/benjiweber.co.uk\/blog\/#\/schema\/person\/45ecb36b51f4ce99e6929d2d31ca5c09\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/benjiweber.co.uk\/blog\/2013\/12\/06\/strictmocks-in-mockito\/\"]}]},{\"@type\":\"Person\",\"@id\":\"https:\/\/benjiweber.co.uk\/blog\/#\/schema\/person\/45ecb36b51f4ce99e6929d2d31ca5c09\",\"name\":\"benji\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/benjiweber.co.uk\/blog\/#personlogo\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/05fb47b31a0b329e1b790074a9b624ef?s=96&d=mm&r=g\",\"caption\":\"benji\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","amp_enabled":true,"_links":{"self":[{"href":"https:\/\/benjiweber.co.uk\/blog\/wp-json\/wp\/v2\/posts\/307"}],"collection":[{"href":"https:\/\/benjiweber.co.uk\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/benjiweber.co.uk\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/benjiweber.co.uk\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/benjiweber.co.uk\/blog\/wp-json\/wp\/v2\/comments?post=307"}],"version-history":[{"count":18,"href":"https:\/\/benjiweber.co.uk\/blog\/wp-json\/wp\/v2\/posts\/307\/revisions"}],"predecessor-version":[{"id":325,"href":"https:\/\/benjiweber.co.uk\/blog\/wp-json\/wp\/v2\/posts\/307\/revisions\/325"}],"wp:attachment":[{"href":"https:\/\/benjiweber.co.uk\/blog\/wp-json\/wp\/v2\/media?parent=307"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/benjiweber.co.uk\/blog\/wp-json\/wp\/v2\/categories?post=307"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/benjiweber.co.uk\/blog\/wp-json\/wp\/v2\/tags?post=307"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}