Access JumpStart 2.0 | Blog

A Rapid Development Framework for Microsoft Access

See yesterday’s message in the archive here:

Writing tests for legacy code – Part 2 | Access JumpStart

For reference, here is the full function I am discussing.

'@TestMethod("DeleteAction")
Private Sub GivenConcreteGroupDeleteTriggered_WhenReadOnlyStatusType_RequirePassword()
    On Error GoTo TestFail
    
    'Arrange:
    Dim LineController As ECI_POLineController
    Set LineController = New ECI_POLineController
    Dim testDictionary As New Scripting.Dictionary
    testDictionary.Add "Cost_Type_ID", "2"
    testDictionary.Add "Product_Type_ID", "1"
    testDictionary.Add "Qty_Ordered", "10"
    testDictionary.Add "Phase_Number", "10"
    testDictionary.Add "Item_Description", "Test Description"
    testDictionary.Add "Qty_Used", "10"
    testDictionary.Add "Unit_of_Measure", "EA"
    testDictionary.Add "Taxable", "True"
    testDictionary.Add "Concrete_Minutes_Apart", "15"
    testDictionary.Add "Line_Status", STATUS_OPEN
    
    'Act:
    Dim frmGet As New FormValueGetter_Test
    Dim PwCount As New T_PasswordsAlwaysTrueCounter
    Set frmGet.FieldValues = testDictionary
    Set LineController.frmGet = frmGet
    Set LineController.Controller = New T_PoScreenControllerAddModeWritable
    LineController.ExecFormDelete New T_StatusConcreteGroupLinesReadOnly, PwCount
    
    'Assert:
    Assert.AreEqual CLng(1), PwCount.Counter

TestExit:
    '@Ignore UnhandledOnErrorResumeNext
    On Error Resume Next
    
    Exit Sub
TestFail:
    Assert.Fail "Test raised an error: #" & Err.Number & " - " & Err.Description
    Resume TestExit
End Sub

I will discuss the Arrange section next:

    'Arrange:
    Dim LineController As ECI_POLineController
    Set LineController = New ECI_POLineController

This is pretty straightforward in that it’s creating the object I’m testing. ECI_POLineController is a class that has the method I want to test. So we are creating a variable of that object type, then setting the variable to a new object of that type.

    Dim testDictionary As New Scripting.Dictionary
    testDictionary.Add "Cost_Type_ID", "2"
    testDictionary.Add "Product_Type_ID", "1"
    testDictionary.Add "Qty_Ordered", "10"
    testDictionary.Add "Phase_Number", "10"
    testDictionary.Add "Item_Description", "Test Description"
    testDictionary.Add "Qty_Used", "10"
    testDictionary.Add "Unit_of_Measure", "EA"
    testDictionary.Add "Taxable", "True"
    testDictionary.Add "Concrete_Minutes_Apart", "15"
    testDictionary.Add "Line_Status", STATUS_OPEN

Next, I am creating a standard dictionary object I’m going to use to simulate getting values from a form. The index of the dictionary (e.g. “Cost_Type_ID”) is going to represent the field name. The value of the dictionary (e.g. “2”) is going to represent the current value in that field.

A big problem with the testing is that I needed to have valid line values on the form, but the form wouldn’t actually be open when I wanted to run the test. It would be a big hot mess to try to open the form and load it properly so that I could then test it and it would require me to use real records and it would be very slow. Not to mention I would likely need to display the form on the screen if I was testing that way.

This problem is referred to as a dependency problem. There are a lot of dependencies that I would have had to have set up for the ECI_POLineController to function properly as it was originally designed. In order to put this function under test, I need to break all those dependencies for the test. The trick is to make sure I’m still actually testing the same code in the test that I will be running when I run the form. We’ll dig more into that tomorrow.