Static mocking is one of the advanced features supported in Telerik JustMock.
It allows you to fake static constructors, methods and properties calls, set expectations and verify results using the AAA principle.
Whether you mock static or instance calls there isn't much difference in the way your organize and write your tests.
We can divide static mocking into the following major parts:
- Static constructor mocking
- Static method mocking
- Extension methods mocking
Note |
|---|
This feature is available only in the commercial version of Telerik JustMock. Refer to this topic to learn more about the differences between both the commercial and free versions of Telerik JustMock. |
Further in this topic we will use the following sample code to illustrate how to mock static constructors, methods and properties.
CopyC#
public class Foo
{
static Foo()
{
throw new NotImplementedException();
}
public static void Submit()
{
}
public static int Execute(int arg)
{
throw new NotImplementedException();
}
public static int FooProp
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
}
internal class FooInternal
{
internal static void DoIt()
{
throw new NotImplementedException();
}
}
public static class FooStatic
{
public static void Do()
{
throw new NotImplementedException();
}
}
CopyVB
Public Class Foo
Shared Sub New()
Throw New NotImplementedException()
End Sub
Public Shared Sub Submit()
Throw New NotImplementedException()
End Sub
Public Shared Function Execute(arg As Integer) As Integer
Throw New NotImplementedException()
End Function
Public Shared Property FooProp As Integer
Get
Throw New NotImplementedException()
End Get
Set(value As Integer)
Throw New NotImplementedException()
End Set
End Property
End Class
Friend Class FooInternal
Friend Shared Sub DoIt()
Throw New NotImplementedException()
End Sub
End Class
Public NotInheritable Class FooStatic
Private Sub New()
End Sub
Public Shared Sub [Do]()
Throw New NotImplementedException()
End Sub
End Class
Static Constructor Mocking
In the following example you will see how you can specify the behavior of the static constructor when the target type is mocked. The first thing you need to do is to set up the target type for mocking all static calls. You do this using one of the following calls to the Mock.SetupStatic method.
| C# | Copy |
|---|
void Mock.SetupStatic( Type staticType );
void Mock.SetupStatic( Type targetType, Behavior behavior );
void Mock.SetupStatic( Type staticType, StaticConstructor staticConstructor );
void Mock.SetupStatic( Type targetType, Behavior behavior, StaticConstructor staticConstructor );
|
As you can see you have a number of choices. You always have to provide the type of the target class you want to set up for mocking. You can also specify the behavior of the mock. The default behavior is Behavior.Loose.
The StaticConstructor parameter defines the default behavior of the static constructor. You can choose from the following values:
The default value for this property is
NonMocked.
Let's see a complete example using the class Foo from the sample code in the beginning.
CopyC#
[TestMethod]
public void ShouldArrangeStaticFunction()
{
Mock.SetupStatic(typeof(Foo), StaticConstructor.Mocked);
int expected = 0;
Mock.Arrange(() => Foo.FooProp).Returns(0);
Assert.AreEqual(expected, Foo.FooProp);
}
CopyVB
<TestMethod()>
Public Sub ShouldArrangeStaticFunction()
Mock.SetupStatic(GetType(Foo), StaticConstructor.Mocked)
Dim expected As Integer = 0
Mock.Arrange(Function() Foo.FooProp).Returns(0)
Assert.AreEqual(expected, Foo.FooProp)
End SubHere we have set up the static constructor mock of the target type Foo. Using the StaticConstructor parameter in the call to SetupStatic we have specified that we want to mock the call to the static constructor and therefore the call to the Foo.FooProp will not throw a NotImplementedException.
General Static Method Mocking
Let's start with the simplest example, namely how to mock the static Submit method. First, we need to call the following:
| C# | Copy |
|---|
Mock.SetupStatic(typeof(Foo), StaticConstructor.Mocked);
|
| Visual Basic | Copy |
|---|
Mock.SetupStatic(GetType(Foo), StaticConstructor.Mocked)
|
This call setups the Foo type for static mocking and prepares all the static methods as mockable.
This is actually the only difference between static and instance mocking. From now on you continue as if you are mocking instance methods.
Let's act.
| C# | Copy |
|---|
Foo.Submit();
|
| Visual Basic | Copy |
|---|
Foo.Submit()
|
In the Submit method implementation we throw an exception, but as we mocked the Foo class that exception should not be thrown.
Finally, we can assert that the method was actually called.
| C# | Copy |
|---|
Mock.Assert(() => Foo.Submit());
|
| Visual Basic | Copy |
|---|
Mock.Assert(Sub() Foo.Submit())
|
With Mock.SetupStatic(typeof(Foo), StaticConstructor.Mocked); we setup that all static methods
from this class will me mocked. In certain cases you'd need to mock only methods that are setup with Mock.Arrange.
To achieve this you need to set the Behavior to Strict in the Mock.SetupStatic call.
CopyC#
[TestMethod]
[ExpectedException(typeof(MockException))]
public void ShouldThrowWhenNotArranged()
{
Mock.SetupStatic(typeof(Foo), Behavior.Strict, StaticConstructor.Mocked);
Mock.Arrange(() => Foo.Execute(10)).Returns(10);
Assert.AreEqual(10, Foo.Execute(10));
Foo.Submit();
}
CopyVB
<TestMethod()>
<ExpectedException(GetType(MockException))>
Public Sub ShouldThrowWhenNotArranged()
Mock.SetupStatic(GetType(Foo), Behavior.Strict, StaticConstructor.Mocked)
Mock.Arrange(Function() Foo.Execute(10)).Returns(10)
Assert.AreEqual(10, Foo.Execute(10))
Foo.Submit()
End Sub
Once we set the Behavior to Strict, only calls setup through arrange are mocked.
Other calls will throw a MockException.
Follows an example of mocking static method in F#:
| F# | Copy |
|---|
[<Test()>]
member this.ShouldMockStaticCall() =
Mock.SetupStatic<Foo>()
Mock.Arrange(fun ignore -> Foo.EchoStatic()).Returns(1);
Assert.AreEqual(1, Foo.EchoStatic())
|
The static EchoStatic method is arranged to return 1.
Mocking Static Property Get
You can also set up a static property get:
CopyC#
[TestMethod]
public void ShouldFakeStaticPropertyGet()
{
Mock.SetupStatic(typeof(Foo), Behavior.Strict, StaticConstructor.Mocked);
bool called = false;
Mock.Arrange(() => Foo.FooProp).DoInstead(() => { called = true; }).Returns(1);
Assert.AreEqual(Foo.FooProp, 1);
Assert.IsTrue(called);
}
CopyVB
<TestMethod()>
Public Sub ShouldFakeStaticPropertyGet()
Mock.SetupStatic(GetType(Foo), Behavior.Strict, StaticConstructor.Mocked)
Dim called As Boolean = False
Mock.Arrange(Function() Foo.FooProp).DoInstead(Sub() called = True).Returns(1)
Assert.AreEqual(Foo.FooProp, 1)
Assert.IsTrue(called)
End SubWe replace the actual implementation of Foo.FooProp with called = true; and return 1.
After acting we verify that the method was actually called with return value 1.
Mocking Static Property Set
Now, let's mock a static property set. In the example below, we arrange the Foo.FooProp property.
We use DoInstead to set a local boolean variable to true once it is assigned 10.
After that, we verify that what we have expected actually happened in our test.
CopyC#
[TestMethod]
public void ShouldFakeStaticPropertySet()
{
Mock.SetupStatic(typeof(Foo), Behavior.Strict, StaticConstructor.Mocked);
bool called = false;
Mock.ArrangeSet(() => { Foo.FooProp = 10; }).DoInstead(() => { called = true; });
Foo.FooProp = 10;
Assert.IsTrue(called);
}
CopyVB
<TestMethod()>
Public Sub ShouldFakeStaticPropertySet()
Mock.SetupStatic(GetType(Foo), Behavior.Strict, StaticConstructor.Mocked)
Dim called As Boolean = False
Mock.ArrangeSet(Sub() Foo.FooProp = 10).DoInstead(Sub() called = True)
Foo.FooProp = 10
Assert.IsTrue(called)
End SubGo to Mock Properties topic to learn more about mocking properties.
Mocking Internal Static Call
Going further, you can mock internal methods like in the following example.
CopyC#
[TestMethod]
public void ShouldFakeInternalStaticCall()
{
Mock.SetupStatic<FooInternal>();
FooInternal.DoIt();
}
CopyVB
<TestMethod()>
Public Sub ShouldFakeInternalStaticCall()
Mock.SetupStatic(Of FooInternal)()
FooInternal.DoIt()
End SubHere, calling FooInternal.DoIt should not throw an exeption as you are
allowed to setup static internal methods.
Mocking Static Class
In the demonstrated examples, the class itself that we mock is a non static class - only the methods
are static. To mock a static class you need to use the non generic version of the
Mock.SetupStatic method, i.e.
CopyC#
[TestMethod]
public void ShouldMockStaticClass()
{
Mock.SetupStatic(typeof(FooStatic));
FooStatic.Do();
}
CopyVB
<TestMethod()>
Public Sub ShouldMockStaticClass()
Mock.SetupStatic(GetType(FooStatic))
FooStatic.[Do]()
End Sub
Mocking Extension Methods
An extension method is a new language feature of C# starting with the 3.0 specifications,
as well as Visual Basic.NET starting with 9.0. Extension methods enable you to "add" methods to existing
types without creating a new derived type, recompiling, or otherwise modifying the original type.
Extension methods are a special kind of static methods, but they are called as if they were instance methods on
the extended type.
Mocking extension method is similar to mocking any instance methods. The only difference is that we don’t need
Mock.Create<T>() call to initialize the class for mocking as extension
mocking is by default partial.
Let's see an example of how to mock extension methods. Consider the following class:
CopyC#
public class Bar
{
public void Execute()
{
throw new NotImplementedException();
}
}
CopyVB
Public Class Bar
Public Sub Execute()
Throw New NotImplementedException()
End Sub
End Class
And a class that contains extension methods for the Foo class:
CopyC#
public static class BarExtensions
{
public static int Echo(this Bar foo, int arg)
{
return default(int);
}
}
CopyVB
Public Module BarExtensions
<System.Runtime.CompilerServices.Extension()>
Public Function Echo(foo As Bar, arg As Integer) As Integer
Return 0
End Function
End Module
Let's mock the Echo extension method.
CopyC#
[TestMethod]
public void ShouldFakeExtensionMethod()
{
var foo = new Bar();
Mock.Arrange(() => foo.Echo(10)).Returns(11);
var actual = foo.Echo(10);
Assert.AreEqual(11, actual);
}
CopyVB
<TestMethod()>
Public Sub ShouldFakeExtensionMethod()
Dim foo = New Bar()
Mock.Arrange(Function() foo.Echo(10)).Returns(11)
Dim actual = foo.Echo(10)
Assert.AreEqual(11, actual)
End Sub
First we create an instance of the Foo class. Notice that
we create a standard instance of the class, not a mock instance. Then we setup the call to Echo
through Arrange in the same way we do it for non static methods. Finally, we assert the return value as usual.
See Also