Rhino Mocks 2.4.2: The Unmocker Okay, so I've a new release out (any time I push out a release, I just know that I'll have to have a new one ready in a short time). So, what is the story here? Some time ago I added the ability to easily create stub objects and dynamic mocks. So you could do something like this:
IList list = mocks.DynamicMock<IList>(); SetupResult.For(list.Count).Return(5); mocks.ReplayAll(); //use list, list.Count will always return 5, anything else will return 0 or null
This works fine and I use it daily in my current project, but it's a problem where you get cases where you have a property on your mocked object, let's take this code:
public int SetId(Something something) { something.Prop = // Get the id return something.Prop; }
Now, what do you need in order to connect the setter and getter in this case? Well, before 2.4.2 you needed to know about the value beforehand, which was not always possible. Here is how you do it on 2.4.2, however:
[Test] public void TestSetId() { Something something = mocks.DynamicMock<Something>(); SetupResult.For(something.Prop).CallOriginalMethod(); // for the getter SetupResult.For(something.Prop = 0).CallOrigianlMethod(); // for the setter Assert.AreEqual(5, objUnderTest.SetId(Something)); }
What do we have here? We create the mock object, and then we setup two calls, one for the property getter and another for the setter (the syntax may be a little weird for the setter, but it's actually the best syntax that we could think of). We tell Rhino that when it get a call to get_Prop, it should just call the original method on the object, and the same for set_Prop. That is a nice way to do it, I think. Caveats:
- There is no either/or with this, it doesn't attempt to match arguments to see if it should call the original method or not, it just does.
- You can't set repeats or exceptions or return values, any call for this method will go to the original object.
- You can't use it on interfaces or abstract methods, since there isn't a method there to pass it to.
Rhino Mocks 2.4 - More on DRY As I said, I update the minor version number every time I add a big feature, this time it's all about DRY and .Net 2.0. From the start Rhino Mocks was capable of being used on the 2.0 framework, but its home was the 1.1. That caused some pain to me every single time that I had to write something like:
IDemo demo = (IDemo) mocks.CreateMock(typeof(IDemo));
Just count the number of times that I repeat the type of the mock object here, three times! This is stupid and it violate the DRY principal in a fairly big way. Unfortantely, there is no good way to resovle this issue on the 1.1 framework, but there is using the 2.0. Generics! {Excuse me while I sing the joy of no more custom collections}. The goal was to reach this:
IDemo demo = mocks.CreateMock<IDemo>();
The first thing to do was to test Rhino Mocks in mocking a generic interface:
[Test]
public void MockAGenericInterface()
{
using (MockRepository mocks = new MockRepository())
{
IList<int> list = mocks.CreateMock < IList<int> >();
Assert.IsNotNull(list);
Expect.Call(list.Count).Return(5);
mocks.ReplayAll();
Assert.AreEqual(5, list.Count);
}
}
I run this test, and it passed! Did I mention that I dig DynamicProxy yet? I then started to clean up some warning about obsolete interfaces (no one wants to hear that their code is obsolete, right?) which I managed to do cleanly and easily, then I moved to take care of the collections. I've mentioned in the past that I've had problems with custom collections becoming too big (40% of the application code), so I was very eager to use them. I had a problem with replacing a hash table with a Dictionary<T> because of the KeyNotFoundException, which I was aware of, but didn't really pay attention to. The tests made it really easy to pin point the problem (although 80+ failing tests did make my heart go THUD!), which was very easy to fix (and I was using the indexer in just one place, strange). That done, I change MockRepository to a partial class, and put all the generic methods in a seperate file (I really like this, btw). That was merely a matter of adding a couple of T and typeof(T) in the right places and I was done. A couple of tests and I was done, .Net 2.0 & generics support! One thing to note:
Rhino Mocks remains compatible with the 1.1 framework and will continue to do so for the foreseeable future!
Users of the 2.0 framework version would get a mocking framework that allows them to use generics to specify the mock objects, that internally uses the System.Collections.Generics and that is all.
The downloads are at the usual place and the API Documentation has been updated. I've yet to update the documentation itself, but I'll do it later today, I hope |
Rhino Mocks 2.3.5 and events The release is available here. Another bug fix release, this time allowing to mock interfaces that inherits from IClonaeble. But this isn't the reason for the post, I wanted to talk about using events in a mocking framework. As events are such an important part of the .Net framework, I decided (encouraged by a user question) to check to see how it works. I wasn't surpirsed (DynamicProxy is cool) to see it was already inside and very easy to do. Here is how you check that the object under test subscribe to an event on a mock object:
public interface IWithEvents
{
event EventHandler Blah;
void RaiseEvent();
}
[Test]
public void VerifyingThatEventWasAttached()
{
using(MockRepository mocks = new MockRepository())
{
IWithEvents events = (IWithEvents)mocks.CreateMock(typeof(IWithEvents));
events.Blah+=new EventHandler(events_Blah);
mocks.ReplayAll();
MethodThatSubscribeToEventBlah(events);
}
}
public void MethodThatSubscribeToEventBlah(IWithEvents events)
{
events.Blah+=new EventHandler(events_Blah);
}
You just record that you want to subscribe to the event and then run the code that is supposed to subscribe to it. Now, let's try do it from the other side, how do check that an event was raised? Well, that is a little more complicated, but not very much so. We need to do create an interface with a matching method name, create a mock from this interface, and then just subscribe to the event and record any expectations regarding the method. As usual, the code is clearer then the explanation:
public interface IEventSubscriber
{
void Hanlder(object sender, EventArgs e);
}
public class WithEvents : IWithEvents
{
#region IWithEvents Members
public event System.EventHandler Blah;
public void RaiseEvent()
{
if (Blah!=null)
Blah(this, EventArgs.Empty);
}
#endregion
}
[Test]
public void VerifyingThatAnEventWasFired()
{
using(MockRepository mocks = new MockRepository())
{
IEventSubscriber subscriber = (IEventSubscriber)mocks.CreateMock(typeof(IEventSubscriber));
IWithEvents events = new WithEvents();
// This doesn't create an expectation because no method is called on subscriber!!
events.Blah+=new EventHandler(subscriber.Hanlder);
subscriber.Hanlder(events, EventArgs.Empty);
mocks.ReplayAll();
events.RaiseEvent();
}
}
One thing to notice here is that subscribing to the event does not create an expectation, since no action is taken on the subscriber instance. Then, to create an expectation that the method will be raised with the specified arguments, we just call the method we just subscribed. Since the raised event will eventually resolve itself to the same method call, everything works as expected. Expect more Rhino Mocks goodies later today
Rhino Mocks 2.1 I've updated Rhino Mocks, this time it's a feature adding release rather than a bug fix release. The issue is very simple, previously, when you wanted to set an expectaion on a method with a return value you needed to to this:
Expect.On(projectView).Call(projectView.Title).Return("ayende");
This is very nice way to do things, but it is does violate the DRY prinicpal. In this case, there are some valid reasons for this syntax. Considerring that Expect is a static class, I don't have any context to rely on here. I needed some way to get the proxy instance that called the last method. But I can't get it from the Call() method, since what I get from that is the return value and not the proxy object itself. The desired thing is to drop the first On(projectView) method call entirely, since in most cases I can just get the last method call for any proxy and that would be the Right Thing to do. Unfortantely, I fear that I let the fear of programmer abuse to come in the path of the common use case.
James Robertson talks about it quite often, but I didn't think that I woulf fall for it. I just got a very well written request Geert (no blog) about this which caused me to smack my hand to my forehead in shame. Therefore, from now on, you can write:
Expect.Call(projectView.Title).Return("ayende");
Now we retain the DRY pricipal Some words of caution, though. This is implemented using static variable which is shared across all repositories and, of course, all threads. Do not try to use it in multi threaded scenario (the Xml comment state so explicitly). There shouldn't be any confusion in a mutli repository cases as long as you don't try to cheat on purpose. That said, this is certainly a most common case and it's a very likely that it'll be an improvement for Rhino Mocks users. The repostiory and the download page has been updated. Happy mocking
Rhino Mocks 2.0.6 Okay, this release is actually an interesting one. The problem it solves is running Rhino Mocks on the .Net 2.0 Framework. Somewhere deep in the bowels of Rhino Mocks, there is a method that return a default value for method that are called during the recording phase, it looks like this:
public
static
object
DefaultValue(Type type) {
if
(type.IsValueType ==
false
)
return
null
;
return
Activator.CreateInstance(type); }
The problem was what would happen when you get a void type [ typeof(void) ]. On .Net 1.0 and 1.1 this just worked, and you actually got a System.Void instance that you could play with. On .Net 2.0, you get a not supported exception, which seems reasonable, except that it breaks my code and that is not reasonable Anyway, on a hunch, I modify the code to do this:
public static object DefaultValue(Type type) { if (type.IsValueType == false || type==typeof(void)) return null; return Activator.CreateInstance(type); }
And now it's working. And no, methods with void return type won't start to return nulls all over the place. Dyamic Proxy handles it, acutally. It simply discard any return value from the interceptor for a method with a void return value, so everything is happy again. I'm currently installing .Net 2.0 and I'll give Rhino Mocks a twirl using C# 2.0, and see if all the tests pass on it. What do you think should change to accomodate 2.0 beyond the obvious:
IAnimal pet = mocks.CreateMock<IAnimal>();
Solved problem of getting virtual method from constructors in DynamicProxy I encountered a problem in Dynamic Proxy, it threw a null reference exception when I tried to run the following code:
proxy = generator.CreateClassProxy(typeof(ArrayList),new StandardInterceptor(), new int[]{1,2,3});
The reason was that ArrayList::ctor(ICollection ) calls a virtual method, and since Dynamic Proxy intercept all dynamic calls, it recieved the call, but before it had time to initialize itself, so it tried to reference a null pointer. I was quite lost as to what to do, this is something that users of Rhino Mocks would likely want to do, and it's a certainly a general problem. I thought that there must be a way to solve that:
public class Base { protected virtual void Init() {} public Base() { Init(); } } public class Derived : Base { string str = "{0}.{1}"; protected override void Init() { str = string.Format(str,1,2); } public Derived() { /*do more work*/ } } public class Derived2 : Base { string str; protected override void Init() { str = string.Format(str,1,2); } public Derived2() { str = "{0}.{1}"
Calling new Derived() will succeed, but calling new Derived2() will fail with null reference exception. Here are the IL for Derived2's constructor:
The constructor for Base is called, which will call init, which will reference str, which is a null, since we set it only after we call Base' constructor. Here is the IL for Derived's constructor:
Here we can see the difference, we first set str, and only then we will call Base' constructor, so this version works. When I figured out what the difference was (and it took some time, I'm not used to reading IL) I approached Dynamic Proxy with dread, I know just about zilch about Reflection.Emit, and Dynamic Proxy has another layer on top of that. However, in the end it took less than an hour, to grok source that I saw for the first time, and then make the changes (moving four lines, that was it). I sent the patch to Castle Project, and I hope they will accept it. |
Mock framework comparison This is just a quicky, doesn't mean much, but allows a look at how each framework's syntax allows to setup a expectation & return value for a method: NMock:
IMock mock = new DynamicMock(typeof(IRequest)); IRequest request = (IRequest)mock.MockInstance; mock.ExpectAndReturn("Username","Ayende"); testedObject.HandleRequest(request); mock.Verify();
EasyMock.Net:
MockControl control = MockControl.CreateControl(typeof(IRequest)); IRequest request = (IRequest)control.GetMock(); control.ExpectAndReturn(request.Username,"Ayende"); control.Replay(); testedObject.HandleRequest(mock); control.Verify();
TypeMock.Net: [Update: This is the correct syntax]
Mock requestMock = MockManager.Mock(typeof(ConcreteRequest)); requestMock.ExpectAndReturn("Username","Ayende"); //TypeMock.Net should take care of intercepting the calls for Username testedObject.HandleRequest(new ConcreteRequest()); MockManager.Verify();
Rhino Mocks Version 1.0:
MockControl mockRequest = MockControl.CreateControl(typeof(IRequest)); IRequest request = (IRequest)mockRequest.MockInstance; mockRequest.ExpectAndReturn(request.Username,"Ayende"); mockRequest.Replay(); testedObject.HandleRequest(request); mockRequest.Verify();
NMock2:
using(Mockery mocks = new Mockery()) { IRequest request = (IRequest)mocks.NewMock(typeof(IRequest),"IRequest"); Expect.Once.On(request).GetProperty("Username").Will(Return.Value("Ayende")); testedObject.HandleRequest(request); }
Rhino Mocks Version 2.0:
using(MockRepository mocks = new MocksRepository) { IRequest request = (IRequest)mocks.CreateMock(typeof(IRequest)); Expect.On(request).Call(request.Username).Return("Ayende"); mocks.ReplayAll(); testedObject.HandleRequest(request); }
Anyone wants to guess who get this editor's prize?
Rhino Mocks V2: Some Progress Made I made quite a progress, mostly thanks to this article. I'm totally and completely blown away by the capabilities of Castle.DynamicProxy, it open up a whole world of facinating possibilities. For instance, I wanted to get rid of this type of code:
MockControl mockView = new MockControl.CreateControl(typeof(IView)); IView view = mockView.MockInstance as IView; view.DoSomething(); mockView.ReturnsFor(3, someVal);
I wanted to be able to do something much simpler, like this:
MockRepository mocks = new MockRepository(); IView view = mocks.CreateMock(typeof(IView)); view.DoSomething(); LastCall.On(view).Returns(someVal).Repeat(3);
It doesn't look like a great improvement, doesn't it? But this means that you no longer has to sync two objects for each mock. I thought a lot about how I would implement this in my code. LastCall is a static class, and has no information about the mocked instance beyond what I'm passing as an argument. I needed some way to get to the MockRepository from the mocked instance. I though about using a static table, with all the mocked instances as keys, and the value being the MockRepository. But this has several disadvantages, chief among them are:
- It's ugly hack.
- It's a huge memory leak, those objects would never be released as long as the AppDomain is loaded.
What I really wanted was to do this:
public static IMethodOptions On(object mockedInstance) { IMockedObject mockedObj = mockedInstance as IMockedObject; //error handling if mockedObj is null return mockedObj.Repository.MethodOptions[mockedInstance]; }
Using Castle.DynamicProxy, it was as easy as modifying the types implemented by the mocked object, and handling the type with the interceptor. It took me some time to figure it out, but when I did, it was so easy that I couldn't believe. So the above code is not possible due to around three or four lines of code. And I'm very pleased to find a new tool. |
Rhino Mocks Future Taking Rhino Mocks to the next level? So I've improved the interface and added constraints and callbacks, this is nice, but I think I can do more. The first issue on the table is ripping some of the innards of the library and replacing them with something saner. I'd to hack quite heavily to get it to the point it's now. Five to six levels of indirections are not fun to go through when you need to understand what is wrong. I also don't agree with some design and implementation decisions that were made. I am also quite excited about the concepts that NMock2 has to offer. Here is what I'm envisioning:
- The explicit record / replay model is very good, and should stay as is.
- Trying to move to implicit model would mean moving to string base expectations, which is unacceptable.
- There needs to be an easier way to spesify constraints / expectations / callbacks and actions.
- Contraints - the same thing as on the NMock world.
- Expectation - what the exact method parameters are.
- Callback - calling your code when a mocked method it called.
- Actions - what to return or to throw when a mocked method is called.
- NMock2 contraints are very easy to read, and should be copied.
- Make the idea of all actions worked on last call explicit in the code. Currently this is implicit, and require deep understanding of the way Rhino Mock is implemented.
- There need to be an easy way to spesify that I'm just expecting a call, and don't care about its arguments, as this is common scenario.
Taking all of this into account, here is how I would like to have tests in Rhino Mocks:
public interface IWalker { void StartWalk(); void WalkFaster(); void EndWalk(); void Rest(TimeSpan howLong); void Drink(int howManyLitters); int CalloriesBurned { get; } int WalkSpeed { get; set; } } [Test] public void IdeadsForRhinoMocks() { IMock mock = new Mock(typeof(IWalker)); IWalker walker = mock.ForType(IWalker); walker.StartWalk(); Set.Result(walker.WalkSpeed,5).Once(); walker.WalkFaster(); Set.Result(walker.WalkSpeed,7).Times(3); Throw.On(walker.Drink(0),new NotEnoughWaterException()).Arguments(Args.IgnoreAll); walker.Rest(new TimeSpan()); LastCall.Arguments(Is.GreaterThan(new TimeSpan(600))); walker.WalkSpeed = 15; LastCall.Callback = new VoidDelegate(ThrowCantWalkThatFast); walker.EndWalk(); mock.Replay(walker); //Or mock.ReplayAll()
ITrainer trainer = new Trainer(Behaviour.Nice); trainer.Walk(walker); }
What do you think of the interface? I also want to add strict method orderring vs. relaxed method ordering. Again, NMock2 show a particular elegant way to do that. |
Rhino Mocks & NMocks 2 I just read Roy's message about NMock2. Vaderpi talks about it in more details, it's look very nice. Here is the original NMock test:
[Test] public void ComputeTotal() { // Create the mock object for item1 and have it return a price of 100 DynamicMock item1Mock = new DynamicMock(typeof(Item)); item1Mock.Strict = true; item1Mock.ExpectAndReturn(\"Price\", 100); Item item1 = (Item) item1Mock.MockInstance;
// Create the mock object for item2 and have it return a price of 50 DynamicMock item2Mock = new DynamicMock(typeof(Item)); item2Mock.Strict = true; item2Mock.ExpectAndReturn(\"Price\", 50); Item item2 = (Item) item2Mock.MockInstance;
// Add the items to the cart ShoppingCart cart = new ShoppingCart(); cart.Add(item1); cart.Add(item2);
// Get the total and make sure it is 150 (100 + 50) int total = cart.ComputeTotal(); Assert.AreEqual(150, total);
// Verify that all the expects have been met item1Mock.Verify(); item2Mock.Verify(); }
Here is the NMock2 version, it looks much clearer, if a bit long.
[Test] public void ComputeTotal() { Mockery mock = new Mockery(); // Create the mock object for item1 and have it return a price of 100 Item item1 = (Item) mock.NewMock(typeof(Item)); Expect.Once.On(item1).GetProperty(\"Price\").Will(Return.Value(100));
// Create the mock object for item2 and have it return a price of 50 Item item1 = (Item) mock.NewMock(typeof(Item)); Expect.Once.On(item1).GetProperty(\"Price\").Will(Return.Value(50));
// Add the items to the cart ShoppingCart cart = new ShoppingCart(); cart.Add(item1); cart.Add(item2);
// Get the total and make sure it is 150 (100 + 50) int total = cart.ComputeTotal(); Assert.AreEqual(150, total);
// Verify that all the expects have been met mock.VerifyAllExpectationsHaveBeenMet(); }
And here is Rhino Mocks version:
[Test] public void ComputeTotal() { //Create mock controls and mock objects MockControl control1 = MockControl.CreateControl(typeof(Item)); MockControl control2 = MockControl.CreateControl(typeof(Item)); Item item1 = (Item)control1.MockInstance, item2 = control2.MockInstance; //Setup return value and expected call control1.ExpectAndReturn(item1.Price,50); control2.ExpectAndReturn(item2.Price,100); //Prepare for replay control1.Replay(); control2.Replay(); //Add items to cart ShoppingCart cart = new ShoppingCart(); cart.Add(item1); cart.Add(item2); // Get total and verify that we got the correct result int total = cart.ComputeTotal(); Assert.AreEqual(150,total); //Verify that all expectations have been met control1.Verify(); control2.Verify(); }
All three version express the same intent. I already talked about why I don't like NMock very much. I didn't have a chance to use NMock2, so I can say if it has any shortcoming, but I* think that there might be a problem in expressing complex conditions.** I'm going to write a code project article for Rhino.Mocks, so far I think that only 1 [] person downloaded it. * Am I spearding FUD? I'm not really objective, you know ** Rhino Mocks solution is to use callbacks and verify the method using Asserts. |
|
|
|
|
|