Rubberduck has been offering IDE-integrated unit test since day one.
But let’s face it: unit testing is hard. And unit testing VBA code that pops a MsgBox isn’t only hard, it’s outright impossible! Why? Because it defeats the purpose of an automated test: you don’t want to be okaying message boxes (or worse, clicking No when the test needed you to click Yes), you want to run the tests and watch them all turn green!
So you had to implement some kind of wrapper interface, and write code that doesn’t call MsgBox directly – like the D of SOLID says, depend on abstractions, not on concrete types.
So you’d code against some IMsgBox wrapper interface:
Option Explicit Public Function Show(ByVal prompt As String, _ Optional ByVal buttons As VbMsgBoxStyle = vbOKOnly, _ Optional ByVal title As String = vbNullString, _ Optional ByVal helpFile As String, _ Optional ByVal context As Long) As VbMsgBoxResult End Function
And then you’d implement the concrete type:
Option Explicit Implements IMsgBox Private Function IMsgBox_Show(ByVal prompt As String, _ Optional ByVal buttons As VbMsgBoxStyle = vbOKOnly, _ Optional ByVal title As String = vbNullString, _ Optional ByVal helpFile As String, _ Optional ByVal context As Long) As VbMsgBoxResult IMsgBox_Show = MsgBox(prompt, buttons, title, helpFile, context) End Function
Now that gets you compilable VBA code, but if you want to write a test for code where the result of a MsgBox call can influence the tested method’s code path, you need to make a fake implementation, and inject that FakeMsgBox into your code, so that your code calls not the real MsgBox function, but the fake implementation.
And if you want to verify that the code setup a vbYesNo message box with the company name as a title, you need to adapt your fake message box and make it configurable.
In other words, setting up fakes by hand is a pain in the neck.
So this is where Rubberduck tests are going:
'@TestMethod Public Sub TestMethod1() On Error GoTo TestFail Fakes.MsgBox.Returns 42 Debug.Print MsgBox("Flabbergasted yet?", vbYesNo, "Rubberduck") 'prints 42 With Fakes.MsgBox.Verify .Parameter "prompt", "Flabbergasted yet?" .Parameter "buttons", vbYesNo .Parameter "title", "Rubberduck" End With TestExit: Exit Sub TestFail: Assert.Fail "Test raised an error: #" & Err.Number & " - " & Err.Description End Sub
Soon. Very soon. Like, next release soon, Rubberduck will begin to allow unit test code to turn the actual MsgBox into a fake one, by setting up a Rubberduck fake.
So yeah, we’re mocking VBA. All of it.
2 thoughts on “Go ahead, mock VBA”
[…] current build contains a number of breakthrough features; I mentioned an actual Fakes framework for Rubberduck unit tests in an earlier post. That will be an ongoing project on its own though; […]
[…] is an entry in their wordpress site giving ideas about the exciting […]