Generics

Telerik® JustMock allows you to mock generic classes/interfaces/methods in the same way as you do it for non-generic ones.

In the next examples we will use the following three sample classes to test:

public class FooGeneric 
{ 
    public virtual TRet Get<T, TRet>(T arg1) 
    { 
        return default(TRet); 
    } 
 
    public virtual int Get<T>() 
    { 
        throw new NotImplementedException(); 
    } 
} 
Public Class FooGeneric 
    Public Overridable Function Get(arg1 As T) As TRet 
        Return Nothing 
    End Function 
 
    Public Overridable Function Get() As Integer 
        Throw New NotImplementedException() 
    End Function 
End Class 

public class FooGenericByRef 
{ 
    public void Submit<T>(out T arg1) 
    { 
        arg1 = default(T); 
    } 
} 
Public Class FooGenericByRef 
    Public Sub Submit(Of T)(ByRef arg1 As T) 
        arg1 = Nothing 
    End Sub 
End Class 

public class FooGeneric<T> 
{ 
    public virtual T Get(T arg) 
    { 
        throw new NotImplementedException(); 
    } 
    public virtual T Get(T arg, T arg2) 
    { 
        throw new NotImplementedException(); 
    } 
 
    public virtual void Execute<T1>(T1 arg) 
    { 
        throw new Exception(); 
    } 
} 
Public Class FooGeneric(Of T) 
    Public Overridable Function Get As T 
        Throw New NotImplementedException() 
    End Function 
 
    Public Overridable Function Get As T 
        Throw New NotImplementedException() 
    End Function 
 
    Public Overridable Sub Execute(Of T1)(arg As T1) 
        Throw New Exception() 
    End Sub 
End Class 

Distinguish Generic Method Calls with Different Arguments

Set up a call to a generic method and distinguish calls depending on the argument type.

[TestMethod] 
public void ShouldDistinguishCallsDependingOnArgumentTypes() 
{ 
    //Arrange 
    var foo = Mock.Create<FooGeneric>(); 
 
    int expextedCallWithInt = 0; 
    int expextedCallWithString = 1; 
 
    Mock.Arrange(() => foo.Get<int>()).Returns(expextedCallWithInt); 
    Mock.Arrange(() => foo.Get<string>()).Returns(expextedCallWithString); 
 
    //Act 
    int actualCallWithInt = foo.Get<int>(); 
    int actualCallWithString = foo.Get<string>(); 
 
    //Assert 
    Assert.AreEqual(expextedCallWithInt, actualCallWithInt); 
    Assert.AreEqual(expextedCallWithString, actualCallWithString); 
} 
<TestMethod()> 
Public Sub ShouldDistinguishCallsDependingOnArgumentTypes() 
    ' Arrange 
    Dim foo = Mock.Create(Of FooGeneric)() 
 
    Dim expectedCallWithInt As Integer = 0 
    Dim expectedCallWithString As Integer = 1 
    Mock.Arrange(Function() foo.Get(Of Integer)()).Returns(expectedCallWithInt) 
    Mock.Arrange(Function() foo.Get(Of String)()).Returns(expectedCallWithString) 
 
    ' Act 
    Dim actualCallWithInt As Integer = foo.Get(Of Integer)() 
    Dim actualCallWithString As Integer = foo.Get(Of String)() 
 
    'Assert 
    Assert.AreEqual(expectedCallWithInt, actualCallWithInt) 
    Assert.AreEqual(expectedCallWithString, actualCallWithString) 
End Sub 

We arrange the Get<T> method to return different values when called with either int or string argument.

The syntax for mocking generic method is:

Mock.Arrange(() => <class_name>.<method_name><type>())...;

After that you act in the same way as you do it for non-generic methods except that you specify argument type. That is:

int actualCallWithInt = foo.Get<int>();

Mock a Generic Method with Out Argument

Set up a call to a generic method with out argument.

[TestMethod] 
public void ShouldMockAGenericMethodWithOutArgs() 
{ 
    //Arrange 
    var foo = Mock.Create<FooGenericByRef>(); 
 
    string expected = "ping"; 
 
    Mock.Arrange(() => foo.Submit<string>(out expected)); 
 
    //Act 
    string actual = string.Empty;      
    foo.Submit<string>(out actual); 
 
    //Assert 
    Assert.AreEqual(expected, actual); 
} 
<TestMethod()> 
Public Sub ShouldMockAGenericMethodWithOutArgs() 
    ' Arrange 
    Dim foo = Mock.Create(Of FooGenericByRef)() 
 
    Dim expected As String = "ping" 
 
    Mock.Arrange(Sub() foo.Submit(Of String)(expected)) 
 
    ' Act 
    Dim actual As String = String.Empty 
    foo.Submit(Of String)(actual) 
 
    ' Assert 
    Assert.AreEqual(expected, actual) 
End Sub 

In the arrange statement we use the out keyword and pass the already initialized variable. It is of type string as we specified the type argument of the Submit method to string. Thus, we arrange that a call to Submit should set the out argument to "ping".

Mock a Generic Class

Set up a call to a method of a generic class.

[TestMethod] 
public void ShouldMockGenericClass() 
{ 
    //Arrange 
    var foo = Mock.Create<FooGeneric<int>>(); 
 
    int expectedValue = 1; 
 
    Mock.Arrange(() => foo.Get(Arg.IsAny<int>())).Returns(expectedValue); 
 
    //Act 
    int actualValue = foo.Get(0); 
 
    //Assert 
    Assert.AreEqual(expectedValue, actualValue); 
} 
<TestMethod()> 
Public Sub ShouldMockGenericClass() 
    ' Arrange 
    Dim foo = Mock.Create(Of FooGeneric(Of Integer))() 
 
    Dim expectedValue As Integer = 1 
 
    Mock.Arrange(Function() foo.Get(Arg.IsAny(Of Integer)())).Returns(expectedValue) 
 
    ' Act 
    Dim actualValue As Integer = foo.Get(0) 
 
    ' Assert 
    Assert.AreEqual(expectedValue, actualValue) 
End Sub 

In this example we mock the generic class FooGeneric<int>. The only difference from mocking non-generic classes is specifying the argument type in the Mock.Create call. After that you act in the same manner when calling non-generic methods.

Here is another example for mocking the Get method:

[TestMethod] 
public void ShouldMockPropertyGet() 
{ 
    //Arrange 
    var genericClass = Mock.Create<FooGeneric<int>>(); 
 
    Mock.Arrange(() => genericClass.Get(1, 1)).Returns(10); 
 
    //Assert 
    Assert.AreEqual(genericClass.Get(1, 1), 10); 
} 
<TestMethod()> 
Public Sub ShouldMockPropertyGet() 
    ' Arrange 
    Dim genericClass = Mock.Create(Of FooGeneric(Of Integer))() 
 
    Mock.Arrange(Function() genericClass.Get(1, 1)).Returns(10) 
 
    ' Assert 
    Assert.AreEqual(genericClass.Get(1, 1), 10) 
End Sub 

In this example we specify that the method accepts only two specific arguments and will return 10.

You can also mock void methods of generic classes. In the next example we mock the Execute method by replacing the implementation so that it sets a boolean value to true.

[TestMethod] 
public void ShouldMockMethodInGenericClass() 
{ 
    //Arrange 
    var genericClass = Mock.Create<FooGeneric<int>>(); 
 
    bool called = false; 
 
    Mock.Arrange(() => genericClass.Execute(1)).DoInstead(() => called = true); 
 
    //Act 
    genericClass.Execute(1); 
 
    //Assert 
    Assert.IsTrue(called); 
} 
<TestMethod()> 
Public Sub ShouldMockMethodInGenericClass() 
    ' Arrange 
    Dim genericClass = Mock.Create(Of FooGeneric(Of Integer))() 
 
    Dim called As Boolean = False 
 
    Mock.Arrange(Sub() genericClass.Execute(1)).DoInstead(Sub() called = True) 
 
    ' Act 
    genericClass.Execute(1) 
 
    ' Assert 
    Assert.IsTrue(called) 
End Sub 

Mock Generic Method in Non-generic Class

Generic methods in non-generic class can also be mocked.

Here is an example:

[TestMethod] 
public void ShouldMockGenericMethodInNonGenericClass() 
{ 
    //Arrange 
    var genericClass = Mock.Create<FooGeneric>(); 
 
    Mock.Arrange(() => genericClass.Get<int, int>(1)).Returns(10); 
 
    //Assert 
    Assert.AreEqual(genericClass.Get<int, int>(1), 10); 
} 
<TestMethod()> 
Public Sub ShouldMockNonGenericMethodInGenericClass() 
    ' Arrange 
    Dim genericClass = Mock.Create(Of FooGeneric)() 
 
    Mock.Arrange(Function() genericClass.Get(Of Integer, Integer)(1)).Returns(10) 
 
    ' Assert             
    Assert.AreEqual(genericClass.Get(Of Integer, Integer)(1), 10) 
End Sub 

First, we arrange that the Get method will be called only with int argument 1 and return int value 10. After that, we verify.

In this article
Not finding the help you need? Improve this article