In the previous text on PrivateObject
I described how private and protected members can be accessed in automated tests.
There's one caveat to this - accessing fields declared WithEvents.
Let's say that you have this dummy class:
Public Class X
Private WithEvents _value As Object
End Class
Then this would be the standard way for accessing the private field:
<TestMethod()>
Public Sub TestX()
Dim x As New X
Dim xAccessor As New PrivateObject(x)
xAccessor.SetField("_value", 5)
. . .
End Sub
But if you try to execute this, you'll get the following error:
System.MissingFieldException: Field 'X._value' not found.
Eh?
Well, the thing is that VB.NET does several things behind the scenes with fields declared WithEvents:
- First, it actually creates a new field, named just like the WithEvents field, but prefixed with an underscore (so, '__value' in this case).
- Second, it changes _value to a property.
- Third, it adds code to manage event handler assignments in the property's setter (handlers declared with the Handles reserved word).
So, actually, the run-time definition of class X looks something like this
(it's actually a bit more complex - you can check the details using a reflector tool like dotPeek):
Public Class X
Private __value As Object
Private Property _value As Object
Get
Return __value
End Get
Set(ByVal value As Object)
' remove handlers defined in Handles declarations
__value = value
' readd handlers defined in Handles declarations
End Set
End Class
So, if we have this in our test code:
xAccessor.SetField("_value", 5)
then, considering the above, there actually is no '_value' field; hence the run-time error.
Two simple solutions should now be obvious:
xAccessor.SetField("__value", 5)
xAccessor.SetProperty("_value", 5)
But I actually prefer this one:
xAccessor.SetFieldOrProperty("_value", 5)
And let PrivateObject figure things out for me. ;-)
Happy testing!
Top
|