{"action":"created","issue":{"url":"https://api.github.com/repos/rubberduck-vba/Rubberduck/issues/1228","repository_url":"https://api.github.com/repos/rubberduck-vba/Rubberduck","labels_url":"https://api.github.com/repos/rubberduck-vba/Rubberduck/issues/1228/labels{/name}","comments_url":"https://api.github.com/repos/rubberduck-vba/Rubberduck/issues/1228/comments","events_url":"https://api.github.com/repos/rubberduck-vba/Rubberduck/issues/1228/events","html_url":"https://github.com/rubberduck-vba/Rubberduck/issues/1228","id":142475856,"number":1228,"title":"MsgBox mock/wrapper","user":{"login":"retailcoder","id":5751684,"avatar_url":"https://avatars.githubusercontent.com/u/5751684?v=3","gravatar_id":"","url":"https://api.github.com/users/retailcoder","html_url":"https://github.com/retailcoder","followers_url":"https://api.github.com/users/retailcoder/followers","following_url":"https://api.github.com/users/retailcoder/following{/other_user}","gists_url":"https://api.github.com/users/retailcoder/gists{/gist_id}","starred_url":"https://api.github.com/users/retailcoder/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/retailcoder/subscriptions","organizations_url":"https://api.github.com/users/retailcoder/orgs","repos_url":"https://api.github.com/users/retailcoder/repos","events_url":"https://api.github.com/users/retailcoder/events{/privacy}","received_events_url":"https://api.github.com/users/retailcoder/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/rubberduck-vba/Rubberduck/labels/test-mock-api","name":"test-mock-api","color":"cdcdcd"},{"url":"https://api.github.com/repos/rubberduck-vba/Rubberduck/labels/unit-testing","name":"unit-testing","color":"DDDDDd"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":3,"created_at":"2016-03-21T21:24:33Z","updated_at":"2016-03-21T21:55:55Z","closed_at":null,"body":"`MsgBox` is a common dependency that can crawl just about everywhere in a code base, and thwart unit testing (because it requires clicking, which defeats automated tests).\r\n\r\nLet's pack a configurable message box wrapper with Rubberduck, that unit tests can use to predetermine the output (as one would with a mock), and that production code can use to actually display a `MsgBox`.\r\n\r\nSomething like this perhaps, in an `IMsgBox` class module:\r\n\r\n\tVERSION 1.0 CLASS\r\n\tBEGIN\r\n\t  MultiUse = -1  'True\r\n\tEND\r\n\tAttribute VB_Name = \"IMsgBox\"\r\n\tAttribute VB_GlobalNameSpace = False\r\n\tAttribute VB_Creatable = False\r\n\tAttribute VB_PredeclaredId = True\r\n\tAttribute VB_Exposed = False\r\n\tOption Explicit\r\n\r\n\tPrivate Type TMsgBox\r\n\t\tIsMock As Boolean\r\n\t\tResult As VbMsgBoxResult\r\n\tEnd Type\r\n\r\n\tPrivate this As TMsgBox\r\n\r\n\tPublic Sub Setup(ByVal value As VbMsgBoxResult)\r\n\tAttribute Setup.VB_Description = \"Configures mock message box result, for testing purposes.\"\r\n\t\tthis.IsMock = True\r\n\t\tthis.Result = value\r\n\tEnd Sub\r\n\r\n\tPublic Sub Release()\r\n\tAttribute Release.VB_Description = \"Releases an instance, which then no longer acts as a test mock.\"\r\n\t\tthis.IsMock = False\r\n\tEnd Sub\r\n\r\n\tPublic Property Get Result() As VbMsgBoxResult\r\n\t\tResult = this.Result\r\n\tEnd Property\r\n\r\n\tPublic Function Show(ByVal prompt As String, Optional ByVal style As VbMsgBoxStyle, Optional ByVal title As String, Optional ByVal helpFile As Variant, Optional ByVal context As Variant) As VbMsgBoxResult\r\n\tAttribute Show.VB_Description = \"Displays the message box and returns the result. If Setup was called, only returns the setup result.\"\r\n\tAttribute Show.VB_UserMemId = 0\r\n\t\t\r\n\t\tIf Not this.IsMock Then\r\n\t\t\tIf title = vbNullString Then title = Application.Name\r\n\t\t\tthis.Result = MsgBox(prompt, style, title, helpFile, context)\r\n\t\tEnd If\r\n\r\n\t\tShow = this.Result\r\n\t\t\r\n\tEnd Function\r\n\r\n\r\nThoughts?\r\n\r\nBecause of the `PredeclaredId` and `UserMemId = 0` attributes, in-code usage could look like this:\r\n\r\n    IMsgBox.Show \"Hi!\"\r\n\r\nOr:\r\n\r\n    If IMsgBox(\"Confirm?\", vbYesNo) = vbYes Then\r\n\r\nThis would be illegal though (compile error / invalid use of property - go figure):\r\n\r\n    IMsgBox \"Hi!\"\r\n\r\n---\r\n\r\nThe benefit is that it makes a fairly easy to use wrapper/substitute for the commonly-used `MsgBox` built-in function, and code that uses the *default instance* would still be configurable globally, so unit tests could do this:\r\n\r\n    IMsgBox.Setup vbYes\r\n\r\nAnd then every single call to `IMsgBox.Show` (implicit or explicit) would return `vbYes`.\r\n\r\nIdeally, user code wouldn't be so tightly coupled with the default instance though - but providing it does feel right. User code would ideally work with a given instance of `IMsgBox`, which test methods could \"inject\" with a given configuration."},"comment":{"url":"https://api.github.com/repos/rubberduck-vba/Rubberduck/issues/comments/199503319","html_url":"https://github.com/rubberduck-vba/Rubberduck/issues/1228#issuecomment-199503319","issue_url":"https://api.github.com/repos/rubberduck-vba/Rubberduck/issues/1228","id":199503319,"user":{"login":"retailcoder","id":5751684,"avatar_url":"https://avatars.githubusercontent.com/u/5751684?v=3","gravatar_id":"","url":"https://api.github.com/users/retailcoder","html_url":"https://github.com/retailcoder","followers_url":"https://api.github.com/users/retailcoder/followers","following_url":"https://api.github.com/users/retailcoder/following{/other_user}","gists_url":"https://api.github.com/users/retailcoder/gists{/gist_id}","starred_url":"https://api.github.com/users/retailcoder/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/retailcoder/subscriptions","organizations_url":"https://api.github.com/users/retailcoder/orgs","repos_url":"https://api.github.com/users/retailcoder/repos","events_url":"https://api.github.com/users/retailcoder/events{/privacy}","received_events_url":"https://api.github.com/users/retailcoder/received_events","type":"User","site_admin":false},"created_at":"2016-03-21T21:55:54Z","updated_at":"2016-03-21T21:55:54Z","body":"Because KISS"}}