Let's say that we have a class that needs a DB connection to perform its operations;
perhaps a SqlBuilder that uses the connection to read foreign key constraints to automatically
add JOIN clauses to the generated query text.
Public Class SqlBuilder
Private _connection as IDbConnection
Public Sub New(ByVal connection As IDbConnection)
_connection = connection
End Sub
. . .
End Class
Whatever the class does later on, it needs a connection when it's being constructed.
And the class needs to be constructed to be tested... ;-)
So, when creating tests for SqlBuilder, we have several options:
-
First, a real instance of a DB connection can be used;
but that ties the test with that specific type of connection (OleDbConnection, SqlConnection, or whatever).
Then you may need an actual database to be able to create that connection.
This quickly turns into a complex setup...
Even if all you're testing is the setter and getter of a simple property...
-
Second, we could create a mock class that implements the interface.
A class that really does nothing - just creates all needed method (property, etc.) stubs.
Not very difficult, but IDbConnection, as in our example,
needs to have about 10 methods / properties implemented.
Some of these are functions or property getters, so we need to provide return values there.
All in all, about 50 lines of dummy code; not really elegant...
Then, if the interface changes (for instance, when the interface is defined in our own code),
we need to update that stub too. Couples the test code just a bit too much to other code...
-
But what if we could somehow automate the second step?
After all, we can get information on all members of an interface, parameters and return types, using reflection...
And that's exactly what Rhino Mocks does - given an interface,
it creates, at runtime, a "dummy" class (the stub) that implements that interface.
In code, this stub can be used wherever that interface is needed.
So, let's say that we have a test class and we're writing a very simple test:
Imports Rhino.Mocks
Public Class SqlBuilderTests
<TestMethod()>
Public Sub TestSomething()
Dim connection As IDbConnection = MockRepository.GenerateStub(Of IDbConnection)()
Dim builder As New SqlBuilder(connection)
. . .
End Sub
. . .
End Class
The generic method MockRepository.GenerateStub(Of I)() generates the class implementing the interface I.
And voila! With one line of code we have the needed stub class...
One thing to remember here, though, is how the generated class behaves at runtime:
-
Calls to procedures of the stub, including property setters for write-only properties, will do nothing.
-
Function return values, including property getters for read-only properties,
will return the default value for the type.
-
For read/write properties, the stub will default to the default value of the property type.
But assignments to the property will be honored, that is, after a property is assigned a value,
that value will be subsequently returned by the getter (and the property can be reassigned multiple times).
HTH
Top
|