{"action":"closed","issue":{"url":"https://api.github.com/repos/spockframework/spock/issues/112","labels_url":"https://api.github.com/repos/spockframework/spock/issues/112/labels{/name}","comments_url":"https://api.github.com/repos/spockframework/spock/issues/112/comments","events_url":"https://api.github.com/repos/spockframework/spock/issues/112/events","html_url":"https://github.com/spockframework/spock/issues/112","id":99907944,"number":112,"title":"Confusing Mocking and Verification","user":{"login":"xnslong","id":11991294,"avatar_url":"https://avatars.githubusercontent.com/u/11991294?v=3","gravatar_id":"","url":"https://api.github.com/users/xnslong","html_url":"https://github.com/xnslong","followers_url":"https://api.github.com/users/xnslong/followers","following_url":"https://api.github.com/users/xnslong/following{/other_user}","gists_url":"https://api.github.com/users/xnslong/gists{/gist_id}","starred_url":"https://api.github.com/users/xnslong/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xnslong/subscriptions","organizations_url":"https://api.github.com/users/xnslong/orgs","repos_url":"https://api.github.com/users/xnslong/repos","events_url":"https://api.github.com/users/xnslong/events{/privacy}","received_events_url":"https://api.github.com/users/xnslong/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/spockframework/spock/labels/not%20a%20bug","name":"not a bug","color":"bfe5bf"},{"url":"https://api.github.com/repos/spockframework/spock/labels/won't%20fix","name":"won't fix","color":"bfe5bf"}],"state":"closed","locked":false,"assignee":null,"milestone":null,"comments":4,"created_at":"2015-08-09T16:01:17Z","updated_at":"2015-08-10T09:34:50Z","closed_at":"2015-08-10T09:34:50Z","body":"I made some changes with a method, so I want to test the logic of this change. But I just feel it difficult to write a test function that reads clearly enough to explain my expectation. The problem is as following.\r\n\r\nThe method I am testing is `foo(input)`, which will call an underlying method `underlyingService.sampleMethod(argObject): Result`. The changes I made will affect the `argObject` passed from the `foo` method, and what I want to test is just the logic with `argObject`. I'm not concerned with the returned `Result` object or any other conditions, if only they could be proper enough to avoid any unrelated exceptions.\r\n\r\nSo I mocked a `Result` object, and it should be returned for any invocation of the `sampleMethod` (because the `foo` method expects a non-null `Result` object from the `sampleMethod`). And when the `foo` method is called, I should verify it that the `argObject` passed from the `foo` method is just as expected. Finally, I wrote the following code that reluctantly meets the test requirement.\r\n\r\n```groovy\r\ndef underlyingService\r\ndef testObject = new TestClass\r\ndef setup() {\r\n    underlyingService = Mock(UnderlyingService)\r\n    testObject.underlyingService = underlyingService\r\n}\r\ndef \"foo method should pass correct argObject\"() {\r\n    setup:\r\n        def result = Mock(Result) {\r\n            // mocked interation declaration\r\n        }\r\n    when:\r\n        testObject.foo(input)\r\n    then:\r\n        1 * underlyingService.sampleMethod({it.bar == expectedBar}) >> result\r\n    where:\r\n        input | expectedBar\r\n        xxx.  | xxxxxxxx\r\n}\r\n```\r\nThe test function will work well when the `foo` method is correctly implemented; but when not implemented correctly, it will report some unexpected failure information (the information I want it to show is that \"argument is not as expected\", but it will show `NullPointerException` about the `result` object in the `foo` method invocation; because the mocked `sampleMethod` is not matched, so a default `Result` object (`null`) will be returned, which is unexpected by the `foo` method). \r\n\r\nAnother important problem is that the `sampleMethod` in the `then:` clause (officially called \"block\", but maybe \"clause\" will be a better word, so I take it.) plays the role of Mocking and Verification at the same time. This is very confusing, because we will always think it that verifications and conclusions should be in the `then:` clause, but prerequisites should not.  The prerequisites should be set in the `setup:` clause (of course, verifications should not be declared here in the `setup:` clause). So the ideal test code that will express my wish is like the following. But it always shows `NullPointerException` whether the `foo` method is implemented correctly or not. The reason of this is that the declaration in the `then:` clause will be matched when the method is invoked, not the declaration in the `setup:` clause; the declaration in the `then:` clause defined no `Result`, so the result returned to the `foo` method will be `null`. \r\n\r\n```groovy\r\ndef underlyingService\r\ndef testObject = new TestClass\r\ndef setup() {\r\n    underlyingService = Mock(UnderlyingService)\r\n    testObject.underlyingService = underlyingService\r\n}\r\ndef \"foo method should pass correct argObject\"() {\r\n    setup:\r\n        def result = Mock(Result) {\r\n            // mocked interation declaration\r\n        }\r\n        underlyingService.sampleMethod(_) >> result  // do mocking\r\n    when:\r\n        testObject.foo(input)\r\n    then:\r\n        1 * underlyingService.sampleMethod({it.bar == expectedBar}) // just do verification\r\n    where:\r\n        input | expectedBar\r\n        xxx   | xxxxxxxx\r\n}\r\n```\r\nThat's all of my problem. I just wonder if there is any other way of writing the code that will satisfy my test requirement, or if we can have a discussion over the issue?"}}