Rubberduck icon indicating copy to clipboard operation
Rubberduck copied to clipboard

Running a unit test which fakes both MsgBox.Returns and InputBox.Returns fails

Open jhoobergs opened this issue 2 years ago • 2 comments

Rubberduck version information

Rubberduck version 2.5.2.5906 loading:
Operating System: Microsoft Windows NT 10.0.19042.0 x64
Host Product: Microsoft Office x86
Host Version: 16.0.14827.20158
Host Executable: EXCEL.EXE;

Description Running a unit test which fakes both MsgBox.Returns and InputBox.Returns fails with "Running a test method failed with an exception".

To Reproduce Steps to reproduce the behavior:

  1. Create the following procedure
Sub TafelVanVermenigvuldiging()
  Dim intGetal As Integer, intTeller As Integer
  intGetal = InputBox("Geef een getal:")
  If intGetal < 1 Or intGetal > 100 Then
    MsgBox "Het getal moet tussen 1 en 100 liggen."
  Else
    For intTeller = 0 To 9
    MsgBox (intTeller & "x" & intGetal & "=" & intTeller * intGetal)
    Next
  End If  
End Sub
  1. Add the following test module
Option Explicit
Option Private Module

'@TestModule
'@Folder("Tests")

Private Assert As Object
Private Fakes As Object

'@ModuleInitialize
Private Sub ModuleInitialize()
    'this method runs once per module.
    Set Assert = CreateObject("Rubberduck.AssertClass")
    Set Fakes = CreateObject("Rubberduck.FakesProvider")
End Sub

'@ModuleCleanup
Private Sub ModuleCleanup()
    'this method runs once per module.
    Set Assert = Nothing
    Set Fakes = Nothing
End Sub

'@TestInitialize
Private Sub TestInitialize()
    'This method runs before every test in the module..
End Sub

'@TestCleanup
Private Sub TestCleanup()
    'this method runs after every test in the module.
End Sub

'@TestMethod("TafelVanVermenigvuldigingen")
Private Sub TafelVanVermenigvulgingenVan20()
    On Error GoTo TestFail
        
    Fakes.InputBox.Returns 20
    Fakes.MsgBox.Returns 20 'if this line or the one above is commented, it works, but you manually need to return the messageboxes or enter a value
    
    TafelVanVermenigvuldiging    
   
    With Fakes.MsgBox.Verify
        .Parameter "prompt", "0x20=0", 1
        .Parameter "prompt", "1x20=20", 2
        .Parameter "prompt", "2x20=40", 3
        .Parameter "prompt", "3x20=60", 4
        .Parameter "prompt", "4x20=80", 5
        .Parameter "prompt", "5x20=100", 6
        .Parameter "prompt", "6x20=120", 7
        .Parameter "prompt", "7x20=140", 8
        .Parameter "prompt", "8x20=160", 9
        .Parameter "prompt", "9x20=180", 10
        .Exactly 10
    End With
        
    
TestExit:
    Exit Sub
TestFail:
    Assert.Fail "Test raised an error: #" & Err.Number & " - " & Err.Description
    Resume TestExit
End Sub

Expected behavior The test runs (and passes).

Logfile

2022-02-08 17:39:16.2080;TRACE-2.5.2.5906;Rubberduck.Common.LogLevelHelper;
	Rubberduck version 2.5.2.5906 loading:
	Operating System: Microsoft Windows NT 10.0.19042.0 x64
	Host Product: Microsoft Office x86
	Host Version: 16.0.14827.20158
	Host Executable: EXCEL.EXE;
2022-02-08 17:39:19.6973;INFO-2.5.2.5906;Rubberduck.Parsing.VBA.RubberduckParserState;RubberduckParserState (555) is invoking StateChanged (Busy);
2022-02-08 17:39:19.7033;TRACE-2.5.2.5906;Rubberduck.UI.Command.MenuItems.CommandBars.AppCommandBarBase;CancellationTokenSource was already disposed for OnParserStateChanged.;
2022-02-08 17:39:19.8713;ERROR-2.5.2.5906;Rubberduck.UnitTesting.TestEngine;Unexpected exceptino while running test method.;System.InvalidCastException: Specified cast is not valid.
   at Rubberduck.UnitTesting.Fakes.MsgBox.MsgBoxCallback(IntPtr prompt, Int32 buttons, IntPtr title, IntPtr helpfile, IntPtr context) in C:\projects\rubberduck\Rubberduck.Main\ComClientLibrary\UnitTesting\Fakes\MsgBox.cs:line 49
   at Rubberduck.VBEditor.ComManagement.TypeLibs.Abstract.IDispatch.Invoke(Int32 dispIdMember, Guid& riid, UInt32 lcid, UInt32 dwFlags, DISPPARAMS& pDispParams, Object& pVarResult, EXCEPINFO& pExcepInfo, UInt32& pArgErr)
   at Rubberduck.VBEditor.ComManagement.TypeLibs.Unmanaged.IDispatchHelper.Invoke(IDispatch obj, Int32 memberId, InvokeKind invokeKind, Object[] args) in C:\projects\rubberduck\Rubberduck.VBEEditor\ComManagement\TypeLibs\Unmanaged\IDispatchHelper.cs:line 121
   at Rubberduck.VBEditor.ComManagement.TypeLibs.TypeInfoVBEExtensions.StdModExecute(String name, Object[] args) in C:\projects\rubberduck\Rubberduck.VBEEditor\ComManagement\TypeLibs\TypeInfoVBEExtensions.cs:line 155
   at Rubberduck.VBEditor.ComManagement.TypeLibs.VBETypeLibsAPI.ExecuteCode(ITypeLibWrapper projectTypeLib, String standardModuleName, String procName, Object[] args) in C:\projects\rubberduck\Rubberduck.VBEEditor\ComManagement\TypeLibs\Public\TypeLibsAPI.cs:line 261
   at Rubberduck.UnitTesting.VBEInteraction.RunTestMethod(ITypeLibWrapper typeLib, TestMethod test, EventHandler`1 assertCompletionHandler, Int64& duration) in C:\projects\rubberduck\Rubberduck.UnitTesting\UnitTesting\VBEInteraction.cs:line 55
   at Rubberduck.UnitTesting.TestEngine.RunTestMethod(ITypeLibWrapper typeLib, TestMethod test) in C:\projects\rubberduck\Rubberduck.UnitTesting\UnitTesting\TestEngine.cs:line 385
2022-02-08 17:39:20.2352;INFO-2.5.2.5906;Rubberduck.Parsing.VBA.RubberduckParserState;RubberduckParserState (556) is invoking StateChanged (Ready);
2022-02-08 17:39:20.2352;TRACE-2.5.2.5906;Rubberduck.UI.Command.MenuItems.CommandBars.AppCommandBarBase;CancellationTokenSource was already disposed for OnParserStateChanged.;

jhoobergs avatar Feb 08 '22 16:02 jhoobergs

Side note, the "Unexpected exceptino" typo should be fixed together with this issue.

Changing the order of the fakes seems to work:

Fakes.MsgBox.Returns 20
Fakes.InputBox.Returns 20

More generally, you need to set the MsgBox first to to all values that you want the Inputbox to have. The following does not work:

Fakes.InputBox.Returns 1000, 1
Fakes.InputBox.Returns 2000, 2
Fakes.InputBox.Returns 300, 3
Fakes.InputBox.Returns 4000, 4
Fakes.InputBox.Returns 500, 5
Fakes.MsgBox.Returns 1

but this does:

Fakes.MsgBox.Returns 1000, 1
Fakes.MsgBox.Returns 2000, 2
Fakes.MsgBox.Returns 300, 3
Fakes.MsgBox.Returns 4000, 4
Fakes.MsgBox.Returns 500, 5
Fakes.MsgBox.Returns 1, 6
Fakes.InputBox.Returns 1000, 1
Fakes.InputBox.Returns 2000, 2
Fakes.InputBox.Returns 300, 3
Fakes.InputBox.Returns 4000, 4
Fakes.InputBox.Returns 500, 5

jhoobergs avatar Feb 21 '22 10:02 jhoobergs