Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't Moq run the overridden ToString method?

Tags:

.net

mocking

moq

In the following code why does mockTest.ToString() return Null?

EDIT: Added comment into example code to show how to fix the problem.

Public Sub Main()

    Try

        Dim test = New TestClass

        If test.ToString <> "stackoverflow rules" Then
            Throw New Exception("Real Failed: Actual value: <" + test.ToString + ">")
        End If

        Dim mock = New Moq.Mock(Of TestClass)()
        mock.SetupGet(Function(m As TestClass) m.Name).Returns("mock value")

        ' As per Mark's accepted answer this is the missing line of 
        ' of code to make the code work.
        ' mock.CallBase = True

        Dim mockTest = DirectCast(mock.Object, TestClass)

        If mockTest.ToString() <> "mock value" Then
            Throw New Exception("Mock Failed: Actual value: <" + mockTest.ToString + ">")
        End If

        Console.WriteLine("All tests passed.")

    Catch ex As Exception

        Console.ForegroundColor = ConsoleColor.Red
        Console.WriteLine(ex.ToString)
        Console.ForegroundColor = ConsoleColor.White

    End Try

    Console.WriteLine()
    Console.WriteLine("Finished!")
    Console.ReadKey()

End Sub

Public Class TestClass

    Public Sub New()
    End Sub

    Public Overridable ReadOnly Property Name() As String
        Get
            Return "stackoverflow rules"
        End Get
    End Property

    Public Overrides Function ToString() As String
        Return Me.Name
    End Function

End Class
like image 543
Tim Murphy Avatar asked Jan 04 '10 10:01

Tim Murphy


1 Answers

Both the Name property and the ToString method on TestClass are virtual/overridable, which means that Moq will mock them.

By default, Moq returns null for members with reference type return types, unless you explicitly tell it to return something else. Since a string is a reference type, it returns null.

You can fix it by setting CallBase to true.

Setting CallBase to true will cause Moq to call the base implementation if you do not explictly define an override:

mock.CallBase = True

In this case, this will instruct the mock to use the base implementation of ToString since no eplicit Setup exists (and thus invoke the Name property, which does have a Setup).

like image 195
Mark Seemann Avatar answered Nov 07 '22 22:11

Mark Seemann