I recently learnt that Boo now supports a DSL-friendly syntax. A while back I created (and almost finished!) a set of syntactic macros in Boo to make using Rhino Mocks much more natural. Creating macros can be hard work though and gets pretty hacky in places.
The new DSL-friendly syntax in Boo means I can achieve 80% of the same easy-reading code, but using only methods and blocks!
In about 10 minutes I whipped up this:
namespace ConsoleDemo
import Systemimport Rhino.Mocksimport Rhino.Mocks.BooDsl.MockDsl
interface IModel: def CalculateScore(input as int) as intinterface IView: def DisplayScore(score as int)interface IPresenter: def Init()class Presenter(IPresenter): _model as IModel _view as IView def constructor(model as IModel, view as IView): _model = model _view = view def Init(): score = _model.CalculateScore(0) _view.DisplayScore(score)def Test_presenter_init(): with_mocks: // Create mocks of the dependencies model = Mocks.CreateMock of IModel() view = Mocks.CreateMock of IView() // Create the object we are testing presenter = Presenter(model, view) // Record what we expect the presenter to // do with its dependencies. record: expect: model.CalculateScore(0) // Set the return value for the // previous mock call. mock_return 42 expect: view.DisplayScore(42) // Now tell the presenter to do its stuff, // so we can verify it behaves correctly. verify: presenter.Init()print "testing..."Test_presenter_init()print "all good!"print "Press any key to continue . . . "Console.ReadKey(true)
The import of "Rhino.Mocks.BooDsl.MockDsl" brings some new methods into scope. with_mocks initializes a MockRepository. "Mocks" is actually a property referencing that repository, so we can call CreateMock, etc, on it. The record and verify methods make use of the Mocks.Record() and Mocks.Playback() methods. I prefer using "verify" to "playback". The "expect" method runs the code in its block, usually that invokes some mock method. It then calls "LastCall.Repeat.Once()" to set up the expectation. The "mock_return" method calls "LastCall.Return(value)" to set up the return value for the last mock call.
This is all a bit messy for now I know. I have just being throwing code down into this prototype to get a feel for what is possible. I reckon this could be really useful for people using Rhino Mocks.
If you like what you've seen or have any ideas let me know.
The DSL methods are as follows:I am aware of more than one glaring danger in the code(!) but it does show what can be done.
namespace Rhino.Mocks.BooDsl
import Systemimport Rhino.Mocks
callable Block()static class MockDsl:
private static _instance as MockDslImpl static def with_mocks(b as Block): _instance = MockDslImpl() b() _instance = null static def record(b as Block): assert _instance != null _instance.Record(b) static def verify(b as Block): assert _instance != null _instance.Verify(b) static def expect(b as Block): assert _instance != null _instance.Expect(b) static def mock_return(value as object): assert _instance != null _instance.MockReturn(value) static Mocks as MockRepository: get: assert _instance != null return _instance.Mocks
private class MockDslImpl: mocks as MockRepository def constructor(): mocks = MockRepository() public Mocks as MockRepository: get: return mocks public def Record(b as Block): using mocks.Record(): b() public def Verify(b as Block): using mocks.Playback(): b() public def Expect(b as Block): b() LastCall.Repeat.Once() public def MockReturn(value as object): LastCall.Return(value)
Remember Me
© Copyright 2008 Andrew Davey Theme Design by Bryan Bell newtelligence dasBlog 1.9.6264.0 | Page rendered at Wednesday, August 20, 2008 8:15:39 AM (GMT Standard Time, UTC+00:00) Pick a theme: BlogXP calmBlue Candid Blue dasBlog Discreet Blog Blue Elegante essence Just Html MadsSimple Mobile Mono Movable Radio Blue Movable Radio Heat nautica022 orangeCream