'Mocks aren't Stubs'. So now, I decide to refractor the code to improve performance and to do it with Visual Basic 2010 using the MSUnitTest framework. So I have already posted about converting from NUnit to MSUnitTest. So adding in the DotNetMock stuff should be a piece of cake, right? Just reference the DotNetMock.dll and away you go. Not so, I try that and I get an error in the tests.
Test method TestMasterList.TestAssemblies.TestGetNewCode threw exception:
System.TypeInitializationException: The type initializer for 'DotNetMock.Assertion' threw an exception. ---> System.SystemException:
Cannot find an appropriate test framework implementation.
At this point I search around for an alternative testing framework for Mock testing and the biggest buzz seems to be about System.TypeInitializationException: The type initializer for 'DotNetMock.Assertion' threw an exception. ---> System.SystemException:
Cannot find an appropriate test framework implementation.
Rhino.Mocks and TypeMock however, the latter is a commercial product. So the problems are; most of the examples are in C#, they make extensive use of lambda expression and what I can find in vb use an older syntax for the mock code. Now, I know nearly nothing about lambda expressions, part of the reason for this exercise is to learn some of the new shiny stuff that has come out over the last 4 or 5 years by refactoring the code to take advantage of this stuff and get some improvement in performance. To do that I want to know my existing tests are working. So I try to learn Rhino.Mocks and start a new project to do it. I decide to implement a view model controller in windows forms with a passive view and the view communicating to the controller using events. The test is failing for reasons that are unclear to me and I have posted to the Google Group (aka Usenet) Rhino.Mocks with this post
So meanwhile while I try to learn Rhino.Mocks and lambda syntax what do I do. DotNetMock is defunct as far as I can tell and from what I have seen in Rhino and other mocking frameworks, it was a dead end approach anyway. However, I have code that uses that approach and I need to get those tests to run. So I decided to create my own replacement for the element of DotNetMock that I use. Essentially I used the DotNetMock.Mock class and the ExpectationCounter. When I created a mock class I inherited from the base DotNetMock.Mock class so that i could use the Verify method to determine that the expectations I had set had been fulfilled. Now expectations were set using the ExpectationCounter as a member level variable in Mock class.
To give an example; for the interface IFoo declared below
Public Interface IFoo
Sub SomeMethod()
End Interface
In the DotNetMock style this would be implemented as a mock class thus;Sub SomeMethod()
End Interface
Public Class MockFoo
Implements IFoo
Private _ExpectSomeMethodCall as New ExpectationCounter("SomeMethod")
Public Sub SetExpectationOnSomeMethod(ByVal expectedCalls as integer)
_ExpectSomeMethodCall.Expect = expectedCalls
End Sub
Public Sub SomeMethod() Implements IFoo.SomeMethod
_ExpectSomeMethodCall.Inc
End Sub
End Class
In this case the mock class would be injected into what ever class that uses it and when your test code would call the MockFoo.Verify method it
would not throw an exception if the number of calls to the "SomeMethod" method matched the value set in the expectation. Now my problem was how to do this
in a testable way that was generic and would not require a custom Verify method in every case of the Mock class in the test projects. Implements IFoo
Private _ExpectSomeMethodCall as New ExpectationCounter("SomeMethod")
Public Sub SetExpectationOnSomeMethod(ByVal expectedCalls as integer)
_ExpectSomeMethodCall.Expect = expectedCalls
End Sub
Public Sub SomeMethod() Implements IFoo.SomeMethod
_ExpectSomeMethodCall.Inc
End Sub
End Class
The answer was to create a custom ExpectationCounter class.
Public Class ExpectationCounter
Private _p1 As String
Sub New(ByVal p1 As String)
_p1 = p1
_receivedCalls = 0
End Sub
Property Expected As Integer
Private _receivedCalls As Integer
Sub Inc()
_receivedCalls += 1
End Sub
Sub Verify()
If Me.Expected = 0 Then Throw New ExpectationException(String.Format("No expectations set for '{0}'", _p1))
If _receivedCalls <> Me.Expected Then
Throw New ExpectationException(String.Format("Expected calls for '{0}' did not occur, Expected {1} got {2}", _p1, Me.Expected, _receivedCalls))
End If
End Sub
End Class
Imports System.Reflection
<clscompliant(true)>
Public Class Mock
Public Sub Verify()
Dim ex() As FieldInfo
Dim isAnExpectationFieldPresent As Boolean = False
ex = Me.GetType.GetFields(BindingFlags.NonPublic Or BindingFlags.Instance)
If ex.Length <= 0 Then Throw New ExpectationException("No expectation fields set")
For Each expectations As FieldInfo In ex
If expectations.GetValue(Me).GetType.ToString = "ArdoughterSoftware.MockFramework.ExpectationCounter" Then
isAnExpectationFieldPresent = True
CType(expectations.GetValue(Me), ExpectationCounter).Verify()
End If
Next
If Not isAnExpectationFieldPresent Then
Throw New ExpectationException("No expectation Field set")
End If
End Sub
End Class
Now this should let me replace the DotNetMock with my own version and get my existing test to run. I would also expect that they would pass since they did the last time I ran tests on this code. Eventually once I figure out Rhino.Mocks I will replace all the DotNetMock/MyMocks with equivalent tests in that system
So then I should be back to my original state but now in VS 2010. Then I can add additional tests to check on performance and then refractor from there. <clscompliant(true)>
Public Class Mock
Public Sub Verify()
Dim ex() As FieldInfo
Dim isAnExpectationFieldPresent As Boolean = False
ex = Me.GetType.GetFields(BindingFlags.NonPublic Or BindingFlags.Instance)
If ex.Length <= 0 Then Throw New ExpectationException("No expectation fields set")
For Each expectations As FieldInfo In ex
If expectations.GetValue(Me).GetType.ToString = "ArdoughterSoftware.MockFramework.ExpectationCounter" Then
isAnExpectationFieldPresent = True
CType(expectations.GetValue(Me), ExpectationCounter).Verify()
End If
Next
If Not isAnExpectationFieldPresent Then
Throw New ExpectationException("No expectation Field set")
End If
End Sub
End Class
Since Rhino.Mock is poorly documented in VB.NET I fully intend to post on my learning experiences and perhaps but a full journal of the development of the fantasy calendar project as future blog posts. It will make the project a bit more complicated that the application requirements might merit but in this case the requirements are to learn the mocking framework and the working fantasy calendar is a secondary target.