Skip to content
Skip to breadcrumbs
Skip to header menu
Skip to action menu
Skip to quick search
Quick Search
Browse
Pages
Blog
Labels
Attachments
Mail
Advanced
What’s New
Space Directory
Feed Builder
Keyboard Shortcuts
Confluence Gadgets
Log In
Sign Up
Dashboard
Groovy
Copy Page
You are not logged in. Any changes you make will be marked as
anonymous
. You may want to
Log In
if you already have an account. You can also
Sign Up
for a new account.
This page is being edited by
.
Paragraph
Paragraph
Heading 1
Heading 2
Heading 3
Heading 4
Heading 5
Heading 6
Preformatted
Quote
Bold
Italic
Underline
More colours
Strikethrough
Subscript
Superscript
Monospace
Clear Formatting
Bullet list
Numbered list
Outdent
Indent
Align left
Align center
Align right
Link
Table
Insert
Insert Content
Image
Link
Attachment
Symbol
Emoticon
Wiki Markup
Horizontal rule
tinymce.confluence.insert_menu.macro_desc
Info
JIRA Issue
Status
Gallery
Tasklist
Table of Contents
Other Macros
Page Layout
No Layout
Two column (simple)
Two column (simple, left sidebar)
Two column (simple, right sidebar)
Three column (simple)
Two column
Two column (left sidebar)
Two column (right sidebar)
Three column
Three column (left and right sidebars)
Undo
Redo
Find/Replace
Keyboard Shortcuts Help
<h1>Groovy Mocks</h1><p>Mock objects are<table class="wysiwyg-macro" data-macro-name="excerpt" data-macro-parameters="atlassian-macro-output-type=INLINE" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2V4Y2VycHQ6YXRsYXNzaWFuLW1hY3JvLW91dHB1dC10eXBlPUlOTElORX0&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="RICH_TEXT"><tr><td class="wysiwyg-macro-body"><p>used to assist (typically unit) testing of classes in isolation</p></td></tr></table>.<br /> The Groovy Mock resides in the <code>groovy.mock.interceptor</code> package. It is an all-groovy mock testing library.</p><p>In principle, it is used like this:</p><table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>import groovy.mock.interceptor.MockFor def mocker = new MockFor(Collaborator.class) // create the Mock support mocker.demand.one(1..2) { 1 } // demand the 'one' method one or two times, returning 1 mocker.demand.two() { 2 } // demand the 'two' method exactly once, returning 2 mocker.use { // start using the Mock def caller = new Caller() // caller will call Collaborator assertEquals 1, caller.collaborateOne() // will call Collaborator.one assertEquals 1, caller.collaborateOne() // will call Collaborator.one assertEquals 2, caller.collaborateTwo() // will call Collaborator.two } // implicit verify for strict expectation here </pre></td></tr></table><p>Groovy Mocks were inspired by <a href="http://www.easymock.org/">EasyMock</a>.</p><p>Find background information about Mocks and endo-testing under <a href="http://www.connextra.com/aboutUs/mockobjects.pdf">XP2000 conference paper</a>.</p><p>For an extended example, see <a class="confluence-link" href="/display/GROOVY/Using+Testing+Frameworks+with+Groovy" data-linked-resource-id="67695" data-linked-resource-type="page" data-linked-resource-default-alias="Using Testing Frameworks with Groovy" data-base-url="http://docs.codehaus.org">Using Testing Frameworks with Groovy</a></p><h2>Features</h2><ul><li>typical mock style of <em>failing early</em></li><li>mocks instance and class methods</li><li>mocks final methods and final Collaborators</li><li>mocks Groovy and Java Collaborators (but Caller must be groovy)</li><li>can mock all objects of a given class (or a single Groovy object)</li><li>mocks even if Collaborator cannot be injected into the Caller</li><li>mocks even if Collaborator is not accessible on the Caller (no getter)</li><li>demanded calls specified via recording calls on the Demand object (EasyMock style).</li><li>cardinality specified as Ranges, default is <code>1..1</code>; 'optional' can be achieved with <code>0..1</code></li><li>behavior specified via Closures, allowing static or calculated return values, throwing exceptions, asserting argument values, etc. (even tricky sequence constraints by sharing state in the testMethod scope between the behavior Closures)</li><li>matching parameter list specified via Closure's parameter list, supporting typed or untyped params, default params, and varargs.</li><li>not dependent on any external mock library</li></ul><p>For an extensive list of usages see the <a href="http://svn.codehaus.org/groovy/trunk/groovy/groovy-core/src/test/groovy/mock/interceptor">unit tests that show how to use the mock package</a>.</p><h3>MockFor Tests</h3><p>Some tests to demonstrate how to use the MockFor class.</p><table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>import grails.test.* import groovy.mock.interceptor.* class MockForTests extends GroovyTestCase { void test_mock_single_method_and_use_as_category() { def mock = new MockFor(MockForTestsClass) mock.demand.amethod { "from mock"} mock.use { assertEquals "from mock", new MockForTestsClass().amethod() } } void test_mock_single_method_using_demand_with_and_use_as_category() { def mock = new MockFor(MockForTestsClass) mock.demand.with { amethod() { "from mock"} } mock.use { assertEquals "from mock", new MockForTestsClass().amethod() } } void test_mock_single_static_method_and_use_as_category() { def mock = new MockFor(MockForTestsClass) mock.demand.astaticmethod { "from static mock"} mock.use { assertEquals "from static mock", MockForTestsClass.astaticmethod() } } void test_mock_method_with_parameters() { def mock = new MockFor(MockForTestsClass) mock.demand.amethodwithparameters { a -> "from mock with parameters ${a}" } mock.use { assertEquals "from mock with parameters 123", new MockForTestsClass().amethodwithparameters(123) } } // This is a special case problem related to a bug. This proves the work around. // The bug is that you can not mock the "find" method unless you pass in the // cardinality as well. void test_mocking_a_method_called_find_is_a_special_case() { def mock = new MockFor(MockForTestsClass) mock.demand.find(1) { "cardinality 1" } mock.use { assertEquals "cardinality 1", MockForTestsClass.find() } } // This illustrates a down side of MockFor. Despite the fact that the MockFor constructor // is passed the type that it is replacing it does no verification that the demands actually // match the signatures of the methods in the real implementation. void test_methods_do_not_have_to_exist_on_a_class_for_them_to_be_mocked() { def mock = new MockFor(Object) mock.demand.aMethodThatDoesNotExist { "SEE IT WORKS ANYWAY" } mock.use { assert "SEE IT WORKS ANYWAY" == new Object().aMethodThatDoesNotExist() } } // This illustrates a down side of MockFor. Despite the fact that the MockFor constructor // is passed the type that it is replacing it does no verification that the demands actually // match the signatures of the methods in the real implementation. void test_demand_the_wrong_number_of_arguments_is_allowed() { def mock = new MockFor(MockForTestsClass) mock.demand.amethodwithparameters { a, extraArg -> "blindly called, changes in implementation ignored" } mock.use { assertEquals "blindly called, changes in implementation ignored", new MockForTestsClass().amethodwithparameters(123, 123) } } void test_mock_single_method_and_use_proxy() { def mock = new MockFor(MockForTestsClass) mock.demand.amethod { "from mock with proxy"} def proxy = mock.proxyInstance() assertEquals "from mock with proxy", proxy.amethod() mock.verify proxy } void test_create_proxy_instance_with_constructor_arguments() { def mock = new MockFor(MockForTestClassWithConstructorArgs) mock.demand.amethod { "from mock with proxy"} def proxy = mock.proxyInstance(["value1", "value2"]as Object[]) assertEquals "from mock with proxy", proxy.amethod() mock.verify proxy } void test_mocking_a_constructor_call() { def mock = new MockFor(MockForTestsClass, true) mock.demand.with { MockForTestsClass() { throw new Exception("YES IT WORKED") } } mock.use { shouldFail Exception, { new MockForTestsClass() } } } // Constructor mocking requires that an instance of a class is returned // and that instance can be cast to the mocked type. void test_mock_a_constructor_that_gets_used() { def mock = new MockFor(MockForTestsClass, true) mock.demand.with { MockForTestsClass() { new Object() as GroovyObject } } mock.use { new MockForTestsClass() } } // If you return the wrong type from this mocked constructor you will get // an error like this which is a little hard to work out: // // java.lang.ClassCastException: java.lang.String cannot be cast to groovy.lang.GroovyObject // void test_mock_a_constructor_that_returns_the_wrong_type() { def mock = new MockFor(MockForTestsClass, true) mock.demand.with { MockForTestsClass() { "THIS IS THE WRONG TYPE BEING RETURNED" } } shouldFail ClassCastException, { mock.use { new MockForTestsClass() } } } // To demand more interactions with the object beyond the constructor the mocked // constructor most return the proxy instance instead. // // NOTE: MockFor constructs an instance of the real class when creating the proxy // instance. This will require that the required parameters are passed in to the // proxyInstance call for forwarding to the real constructor. void test_mock_a_constructor_that_returns_a_proxy_instance() { def mock = new MockFor(MockForTestsClass, true) def theProxyInstance = mock.proxyInstance() mock.demand.with { MockForTestsClass() { theProxyInstance } amethod() { } } mock.use { def testClass= new MockForTestsClass() testClass.amethod() } } } class MockForTestsClass { void amethod() { println "original method" } static void astaticmethod() { println "original static method" } void amethodwithparameters(message) { println "original method with parameters" } } class MockForTestClassWithConstructorArgs extends MockForTestsClass { def arg1 def arg2 MockForTestClassWithConstructorArgs(arg1, arg2) { this.arg1 = arg1 this.arg2 = arg2 } } </pre></td></tr></table><h3>StubFor Tests</h3><p>Some tests to demonstrate how to use the StubFor class.</p><table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>import groovy.mock.interceptor.* class StubForTest extends GroovyTestCase { void test_stub_single_method_no_different_from_mock() { def mock = new StubFor(StubForTestsClass) mock.demand.amethod { "from stub" } mock.use { assertEquals "from stub", new StubForTestsClass().amethod() } } // While we can call stubbed methods many times we still have to specify // a cardinality higher than our expected call count. void test_stub_single_method_but_call_it_many_times() { def mock = new StubFor(StubForTestsClass) mock.demand.amethod(9999) { "from stub" } mock.use { assertEquals "from stub", new StubForTestsClass().amethod() assertEquals "from stub", new StubForTestsClass().amethod() assertEquals "from stub", new StubForTestsClass().amethod() assertEquals "from stub", new StubForTestsClass().amethod() assertEquals "from stub", new StubForTestsClass().amethod() assertEquals "from stub", new StubForTestsClass().amethod() } } void test_stub_single_method_dont_call_it_and_expect_no_errors() { def mock = new StubFor(StubForTestsClass) mock.demand.amethod { "not called" } mock.use { new StubForTestsClass() } } } class StubForTestsClass { void amethod() { println "original method" } } </pre></td></tr></table>
Please type the word appearing in the picture.
Attachments
Labels
Location
Watch this page
< Edit
Preview >
Loading…
Save
Cancel
Next hint
search
attachments
weblink
advanced