In the previous text on PrivateObject and PrivateType
we saw how PrivateObject can be used to access private and protected members of an object under test.
However, sometimes, you may also need to access some of the members of the object's ancestor.
PrivateObject can still be used in that scenario - you just need to construct it using a PrivateType.
Let's say that you have these two dummy classes:
Public Class X
Private _valueX As Integer
End Class
Public Class Y
Inherits X
Private _valueY As Integer
End Class
And you're testing Y; let's assume that to make the test work, you need to set _valueX to some specific value.
(And, as in the previous case, I don't care one little bit whether this is sound test design,
or whether classes should be reworked so that accessing private members is not necessary, and so on - I fully agree;
BUT this is about the situation where you actually DO have to access ancestor's private members.)
This is the standard way of accessing private members:
<TestMethod()>
Public Sub TestY()
Dim y As New Y
Dim yAccessor As New PrivateObject(y)
yAccessor.SetField("_valueX", 5)
. . .
End Sub
But if you try to execute this, you'll get an exception similar to this one:
System.MissingFieldException: Field 'Y._valueX' not found.
A way to get around this is to use a different constructor for PrivateObject,
one that takes a PrivateType parameter:
<TestMethod()>
Public Sub TestYAsX()
Dim y As New Y
Dim yAccessor As New PrivateObject(y, New PrivateType(GetType(X)))
yAccessor.SetField("_valueX", 5)
. . .
End Sub
What this basically does is it tells the accessor that even though you have an instance of class Y there,
it should access its non-public fields using X's declaration, not Y's.
(This also means that you can't access _valueY using this second version of yAccessor -
after all, it's not a part of X's declaration...)
Note that you don't have to do any of this for protected members -
if _valueX was protected, you could've just used the first version of TestMethod to access it.
Happy testing!
Top
|