问题
I have the following object (simplified port from Delphi) under a NUnit test using VS 2012.
Public Class Class1
Private fLoaded As Boolean
Private fSample As String
Private Sub LoadFromDB()
If (fLoaded) Then
Exit Sub
End If
fLoaded = True
' fDataModule.LoadFromDB(Me)
End Sub
Public Property SampleProp() As String
Get
LoadFromDB()
Return fSample
End Get
Set(ByVal value As String)
fSample = value
End Set
End Property
Public Property Loaded() As Boolean
Get
Return fLoaded
End Get
Set(ByVal value As Boolean)
fLoaded = value
End Set
End Property
End Class
The object is suppose to perform a Load-on-Demand when it's properties are accessed. The following Nunit class is testing the property.
Imports NUnit.Framework
<TestFixture> _
Public Class TestClass1
<Test()> _
Public Sub TestProperties()
Dim TheClass As Class1
TheClass = New Class1
TheClass.Loaded = True
TheClass.SampleProp = "Sample"
TheClass.Loaded = False
Assert.AreEqual("Sample", TheClass.SampleProp)
End Sub
End Class
The problem that occurs is that with a breakpoint on the Assert Statement, the class property Loaded shows as True in the debugger, without any of my code having been executed that would set the internal variable. The end result is that my on-demand load will not get executed.
What is changing the value of the property? In Delphi, using DUnit, the class properties behaved as expected.
回答1:
Adrian is correct on this, the Assert line is triggering the flag to set. This issue looked interesting, so I copied it to see what it is doing. I made a few small changes:
Public Class Class1
Private fLoaded As Boolean = False ' vars in MY code are never nothing
Private fSample As String = "" ' without my say so
...
Private Sub LoadFromDB()
If (fLoaded) Then
Exit Sub
End If
fLoaded = True
Debug.Print("Now, all your datas are belong to me.")
End Sub
And in Test class:
Public Sub TestProperties()
Dim TheClass As New Class1
TheClass.Loaded = True
TheClass.SampleProp = "Sample"
TheClass.Loaded = False
TheClass.SampleProp = "Not Sample"
Debug.Assert(("Sample" = TheClass.SampleProp), "Msg")
End Sub
Most of the changes are meaningless. The print line in LoadFromDB()
is meant to determine WHEN from WHERE the load is firing. The Assert IS causing the DataLoad. In Debug it LOOKS spontaneous and freaky to be on the Assert line and jump to to Load procedure but that is how you have it written.
Since GETTING not SETTING a prop triggers the load, TheClass.SampleProp = "Sample"
does nothing as far as the Loaded flag is concerned. So just before the Assert I added:
If TheClass.SampleProp = "Not Sample" Then
Debug.Print("Test did that")
End If
The data does load as a result of the Property Get, AND the Assert no longer does because my new line also sets the loaded flag to true. It is all seems to be working as it should based on how it is written.
EDIT: I reverted the variable declarations and added a Sub New:
Private fLoaded As Boolean
Private fSample As String
Public Sub New()
Debug.Print("New == {0}", fLoaded)
End Sub
New
Always reports the member var as False
. However in Debug, the mouseover does show the Property value as True
.
Oddly, by time you get to the Assert, Loaded
has been set and reset so by then you might expect it to be accurate. If you trace into the Property Get statement in the Assert, you'll see that fLoaded
is initially false. The same thing happens right after
Dim TheClass As New Class1
The mouse pop up displays True even though New just reported False.
Since both errors are resolved by initializing fLoaded
it looks to be an error in the mouseover value display of Loaded
when dealing with uninitialized vars.
The lesson is, initialize variables whenever possible.
回答2:
I had cases where object-preview of the debugger was triggering the getter and therefore the preload of my object.
来源:https://stackoverflow.com/questions/18902042/unexplainable-code-behavior-with-unit-test