Private Accessor
The Telerik JustMock PrivateAccessor feature allows you to call non-public members of the tested code right in your unit tests. The feature is enabled for both Free and Commercial versions of JustMock.
To give examples of how the PrivateAccessor can be used within your tests, we will use the following sample class:
public class ClassWithNonPublicMembers
{
private int Prop { get; set; }
private int MePrivate()
{
return 1000;
}
private static int MeStaticPrivate()
{
return 2000;
}
private T EchoPrivateGeneric<T>(T arg)
{
return arg;
}
private static T EchoStaticPrivateGeneric<T>(T arg)
{
return arg;
}
}
Public Class ClassWithNonPublicMembers
Private Property Prop() As Integer
Get
Return m_Prop
End Get
Set(value As Integer)
m_Prop = Value
End Set
End Property
Private m_Prop As Integer
Private Function MePrivate() As Integer
Return 1000
End Function
Private Shared Function MeStaticPrivate() As Integer
Return 2000
End Function
Private Function EchoPrivateGeneric(Of T)(ByVal arg As T) As T
Return arg
End Function
Private Shared Function EchoStaticPrivateGeneric(Of T)(ByVal arg As T) As T
Return arg
End Function
End Class
Calling Private Methods
The next example will show how to invoke non-public method with the PrivateAccessor:
[TestMethod]
public void PrivateAccessor_ShouldCallMethod()
{
// Act
var inst = new PrivateAccessor(new ClassWithNonPublicMembers());
var actual = inst.CallMethod("MePrivate");
// Assert
Assert.AreEqual(1000, actual);
}
<TestMethod> _
Public Sub PrivateAccessor_ShouldCallMethod()
' Act
Dim inst = New PrivateAccessor(New ClassWithNonPublicMembers())
Dim actual = inst.CallMethod("MePrivate")
' Assert
Assert.AreEqual(1000, actual)
End Sub
To call non-public methods with PrivateAccessor you must:
- Wrap the instance holding the private method
- Call the non-public method by giving its exact name
- Finally, you can assert against its value
Next, we will show how to call non-public methods from a mocked instance:
[TestMethod]
public void ShouldCallArrangedPrivateMethod()
{
// Arrange
var mockedClass = Mock.Create<ClassWithNonPublicMembers>(Behavior.CallOriginal);
Mock.NonPublic.Arrange<int>(mockedClass, "MePrivate").Returns(5);
// Act
var inst = new PrivateAccessor(mockedClass);
var actual = inst.CallMethod("MePrivate");
// Assert
Assert.AreEqual(5, actual);
}
<TestMethod> _
Public Sub ShouldCallArrangedPrivateMethod()
' Arrange
Dim mockedClass = Mock.Create(Of ClassWithNonPublicMembers)(Behavior.CallOriginal)
Mock.NonPublic.Arrange(Of Integer)(mockedClass, "MePrivate").Returns(5)
' Act
Dim inst = New PrivateAccessor(mockedClass)
Dim actual = inst.CallMethod("MePrivate")
' Assert
Assert.AreEqual(5, actual)
End Sub
- Create a mocked instance of your class under test (you can also use original instance object and perform partial mocking later on)
- Arrange your expectations
- Then, create new PrivateAccessor with the mocked instance as an argument
- Call the non-public method by giving its exact name
- Finally, you can assert against its expected return value
Using the steps above and supplying the type arguments you can call non-public generic methods, the sample test looks as following:
[TestMethod]
public void ShouldCallArrangedPrivateGenericMethod()
{
// Arrange
var mockedClass = Mock.Create<ClassWithNonPublicMembers>(Behavior.CallOriginal);
Mock.NonPublic.Arrange<int>(mockedClass, "EchoPrivateGeneric", new Type[] { typeof(int) }, 10).Returns(5);
// Act
var inst = new PrivateAccessor(mockedClass);
var actual = inst.CallMethodWithTypeArguments("EchoPrivateGeneric", new Type[] { typeof(int) }, 10);
// Assert
Assert.AreEqual(5, actual);
}
<TestMethod>
Public Sub ShouldCallArrangedPrivateGenericMethod()
' Arrange
Dim mockedClass = Mock.Create(Of ClassWithNonPublicMembers)(Behavior.CallOriginal)
Mock.NonPublic.Arrange(Of Integer)(mockedClass, "EchoPrivateGeneric", New Type() {GetType(Integer)}, 10).Returns(5)
' Act
Dim inst = New PrivateAccessor(mockedClass)
Dim actual = inst.CallMethodWithTypeArguments("EchoPrivateGeneric", New Type() {GetType(Integer)}, 10)
' Assert
Assert.AreEqual(5, actual)
End Sub
Calling Static Private Methods
The next example will show how to invoke non-public static method with the Telerik JustMock PrivateAccessor:
[TestMethod]
public void PrivateAccessor_ShouldCallStaticMethod()
{
// Act
var inst = PrivateAccessor.ForType(typeof(ClassWithNonPublicMembers));
var actual = inst.CallMethod("MeStaticPrivate");
// Assert
Assert.AreEqual(2000, actual);
}
<TestMethod> _
Public Sub PrivateAccessor_ShouldCallStaticMethod()
' Act
Dim inst = PrivateAccessor.ForType(GetType(ClassWithNonPublicMembers))
Dim actual = inst.CallMethod("MeStaticPrivate")
' Assert
Assert.AreEqual(2000, actual)
End Sub
To call non-public static methods with the PrivateAccessor you must:
- Wrap the instance holding the private method by type
- Call the non-public static method by giving its exact name
- Finally, you can assert against its value
Next, we will show how to call non-public static methods from a mocked instance:
[TestMethod]
public void ShouldCallArrangedStaticPrivateMethod()
{
// Arrange
Mock.SetupStatic(typeof(ClassWithNonPublicMembers));
Mock.NonPublic.Arrange<int>(typeof(ClassWithNonPublicMembers), "MeStaticPrivate").Returns(5);
// Act
var inst = PrivateAccessor.ForType(typeof(ClassWithNonPublicMembers));
var actual = inst.CallMethod("MeStaticPrivate");
// Assert
Assert.AreEqual(5, actual);
}
<TestMethod> _
Public Sub ShouldCallArrangedStaticPrivateMethod()
' Arrange
Dim mockedClass = Mock.Create(Of ClassWithNonPublicMembers)(Behavior.CallOriginal)
Mock.NonPublic.Arrange(Of Integer)(mockedClass, "MeStaticPrivate").IgnoreInstance().Returns(5)
' Act
Dim inst = PrivateAccessor.ForType(GetType(ClassWithNonPublicMembers))
Dim actual = inst.CallMethod("MeStaticPrivate")
' Assert
Assert.AreEqual(5, actual)
End Sub
- Setup your class for static mocking (this is not needed if you are to perform partial mocking later on)
- Arrange your expectations
- Then, create new PrivateAccessor with the mocked instance type as an argument
- Call the non-public method by giving its exact name
- Finally, you can assert against its expected return value
Like a non-public generic instance methods, you can use PrivateAccessor to call non-public generic static ones, here is the sample test:
[TestMethod]
public void ShouldCallArrangedStaticPrivateGenericMethod()
{
// Arrange
Mock.SetupStatic(typeof(ClassWithNonPublicMembers));
Mock.NonPublic.Arrange<int>(typeof(ClassWithNonPublicMembers), "EchoStaticPrivateGeneric", new Type[] { typeof(int) }, 10).Returns(5);
// Act
var inst = PrivateAccessor.ForType(typeof(ClassWithNonPublicMembers));
var actual = inst.CallMethodWithTypeArguments("EchoStaticPrivateGeneric", new Type[] { typeof(int) }, 10);
// Assert
Assert.AreEqual(5, actual);
}
<TestMethod>
Public Sub ShouldCallArrangedStaticPrivateGenericMethod()
' Arrange
Mock.SetupStatic(GetType(ClassWithNonPublicMembers))
Mock.NonPublic.Arrange(Of Integer)(GetType(ClassWithNonPublicMembers), "EchoStaticPrivateGeneric", New Type() {GetType(Integer)}, 10).Returns(5)
' Act
Dim inst = PrivateAccessor.ForType(GetType(ClassWithNonPublicMembers))
Dim actual = inst.CallMethodWithTypeArguments("EchoStaticPrivateGeneric", New Type() {GetType(Integer)}, 10)
' Assert
Assert.AreEqual(5, actual)
End Sub
Get or Set Private Properties
The next example shows how to get or set the value of a non-public property.
[TestMethod]
public void PrivateAccessor_ShouldGetSetProperty()
{
// Act
var inst = new PrivateAccessor(new ClassWithNonPublicMembers());
inst.SetProperty("Prop", 555);
// Assert
Assert.AreEqual(555, inst.GetProperty("Prop"));
}
<TestMethod> _
Public Sub PrivateAccessor_ShouldGetSetProperty()
' Act
Dim inst = New PrivateAccessor(New ClassWithNonPublicMembers())
inst.SetProperty("Prop", 555)
' Assert
Assert.AreEqual(555, inst.GetProperty("Prop"))
End Sub
In the above example, we are: 1. Passing the instance holding the private property to the PrivateAccessor 1. Setting the value of the private property Prop to 555 1. Asserting that, the getter of Prop must return the above set value
Next, we will show how to get an arranged non-public property from a mocked instance:
[TestMethod]
public void ShouldGetArrangedPrivateProperty()
{
// Arrange
var mockedClass = Mock.Create<ClassWithNonPublicMembers>(Behavior.CallOriginal);
Mock.NonPublic.Arrange<int>(mockedClass, "Prop").Returns(5);
// Act
var inst = new PrivateAccessor(mockedClass);
var actual = inst.GetProperty("Prop");
// Assert
Assert.AreEqual(5, actual);
}
<TestMethod> _
Public Sub ShouldGetArrangedPrivateProperty()
' Arrange
Dim mockedClass = Mock.Create(Of ClassWithNonPublicMembers)(Behavior.CallOriginal)
Mock.NonPublic.Arrange(Of Integer)(mockedClass, "Prop").Returns(5)
' Act
Dim inst = New PrivateAccessor(mockedClass)
Dim actual = inst.GetProperty("Prop")
' Assert
Assert.AreEqual(5, actual)
End Sub
- Create a mocked instance of your class under test (you can also use original instance object and perform partial mocking later on)
- Arrange your expectations
- Then, create new PrivateAccessor with the mocked instance as an argument
- Set the non-public property by giving its exact name
- Finally, you can assert against its expected return value
Throw the original exception when calling method
PrivateAccessor is using the reflection API to invoke the required method. When that method throws exception the reflection API is automatically wrapping it in a TargetInvocationException. This could cause inconvenience in determining what the original problem is. PrivateAccessor.RethrowOriginalOnCallMethod is a boolean property that solves that problem by controling whether the original exception should be thrown or not. For backward compatibility the default value is false. To better illustrate the usage of this property consinder the following code sample:
public class Foo
{
private void ThrowsException()
{
throw new NotImplementedException("There is no implementation for this method.");
}
}
Public Class Foo
Private Sub ThrowsException()
Throw New NotImplementedException("There is no implementation for this method.")
End Sub
End Class
And here is how a test for the ThrowsException method will look like:
[TestMethod]
[ExpectedException(typeof(NotImplementedException))]
public void PrivateAccessor_CallMethod_ThrowsException()
{
var instance = new PrivateAccessor(new Foo());
instance.RethrowOriginalOnCallMethod = true;
instance.CallMethod("ThrowsException");
}
<TestMethod>
<ExpectedException(GetType(NotImplementedException))>
Public Sub PrivateAccessor_CallMethod_ThrowsException()
Dim instance = New PrivateAccessor(New Foo())
instance.RethrowOriginalOnCallMethod = True
instance.CallMethod("ThrowsException")
End Sub