I know. There are some really great mocking libraries. The one I’ve used the most is Moq 4. While I’ve not been a regular user of mock libraries. I am fascinated with their usefulness and I’ve recently been thinking about how I might utilize the ServiceWire dynamic proxy to create a simple and easily extended mock library. After a few hours of work this morning, the first experimental of ServiceMock comes to life.
This is not a serious attempt to replace Moq or any other mocking library. It is for the most part a way to demonstrate how to use the dynamic proxy of ServiceWire to do something more than interception or remote procedure call (RPC). It is entirely experimental, but you can get it via NuGet as well.
With ServiceMock, you can now do something like this:
// create your interface
public interface IDoSomething
{
void DoNoReturn(int a, int b);
string DoSomeReturn(string a, string b);
}
// now mock and use the mock
// note: you don't have an implementation of the interface
class Program
{
static void Main(string[] args)
{
var mock = Mock.Make<IDoSomething>();
mock.DoNoReturn(4, 5);
var mockReturnValue = mock.DoSomeReturn("a", "b");
Console.WriteLine(mockReturnValue);
Console.WriteLine("Press Enter to quit.");
Console.ReadLine();
}
}
To create a library that takes advantage of the ServiceWire dynamic proxy, you need a factory (Mock), a channel (MockChannel) that the dynamic proxy will invoke, a channel constructor (MockDefinition) parameter class, and finally an function for invoke and exception handling should the invoke throw (MockActions). And of course, you can supply your own customized function and assign it to the MockActions instance.
The heart of the extensibility is the ability to inject your own “invoke” function via the instance of the MockActions class in the MockDefinition constructor parameter.
var mock = Mock.Make<IDoSomething>(new MockDefinition
{
Id = 1,
Actions = new MockActions
{
Invoke =
(id, methodName, returnType, parameters) =>
{
// do your thing here
var retval = new object[parameters.Length + 1];
// assign your return value to the first object
// in the return array
retval[0] = returnType.Name == "String"
? returnType.ToString()
: TypeHelper.GetDefault(returnType);
//by default, return all parameters as supplied
for (int i = 0; i < parameters.Length; i++)
{
retval[i + 1] = parameters[i];
}
return new object[parameters.Length + 1];
},
InvokeExceptionHandler =
(id, methodName, returnType, parameters, exception) =>
{
//do your custom exception handler if your invoke throws
return true; //return true if you want exception thrown
//return false if you want the exception buried
}
}
});
Here’s the default “invoke” code should you not wish to provide one.
(id, methodName, returnType, parameters) =>
{
Console.WriteLine(id + methodName);
var retval = new object[parameters.Length + 1];
//return params must have returnType
//as first element in the return values
retval[0] = returnType.Name == "String"
? returnType.ToString()
: TypeHelper.GetDefault(returnType);
//by default, return all parameters as supplied
for (int i = 0; i < parameters.Length; i++)
{
retval[i + 1] = parameters[i];
}
return retval;
};
Of course, you might want to log the calls, aggregate counts per methodName or whatever you wish. I hope you find this useful, but I hope more that you will build your dynamic proxy wrapper for your own cool purposes.