Friday, 17 April 2009 01:13 by
hadi
One of the cool features Resharper has is to allow you to define live code templates, i.e. snippets that you can interact with. Say for example you continuously type:
1: var customerServices = new Mock<ICustomerServices>();
each time you want to mock out a service. You could shorten this to only typing:
mock<TAB>customerServices<TAB><ENTER>
and here's how:
1. Resharper -> Live Templates
2. Under User Templates, create a new one
3. Type in: var $name$ = var Mock<I$interface$>();
4. Give it the ShortCut name of "mock" (or whatever you please)
5. On the right-side of the Window, click on the Choose Macro on the name entry
6. Pick Constant Value and close the dialog
7. Click on the Constant Value again on the right-hand side
8. Enter a value, for example mockObject
9. Repeat the same process (Choose Macro) for the interface entry, but this type choose the following option:
10. Set the variable by clicking on another variable link:
11. Choose the variable name
12. Close the editor and you're done. Now watch how it works
Obviously this is just a simple example, but you can see how powerful Live Templates can be.
Wednesday, 15 April 2009 09:00 by
hadi
Having a chat with a colleague the other, brought up the issue of strict mocks. I commented that strict mocks should be used sparingly and only in certain circumstance, and this led to a series of discussions on why that is.
Strict and loose Mocks
Usually mocking frameworks provide two types of mocks: strict and loose. If you're using RhinoMocks, these are called StrictMock and DynamicMock. If you're using Moq, you set the behaviour (Loose = Dynamic = Default or Strict) in the mock creation.
RhinoMocks
RhinoMock has a static mock repository that you can use to create mocks, called MockRepository. This saves you on having to explicitly create a mock repository. Thus, instead of doing:
1: MockRepository mocks = new MockRepository();
2:
3: IDependency dependency = mocks.DynamicMock<IDependency>();
you could write this:
1: IDependency dependency = MockRepository.GenerateMock<IDependency>();
Using the static repository, you cannot pick between dynamic and strict mocks. All mocks are dynamic. This somehow promotes the usage of dynamic mocks over strict ones.
Moq
With Moq, as with RhinoMocks, the default behaviour is of loose mocks. Thus, writing:
1: var dependency = new Mock<IDependency>();
is equivalent to:
1: var dependency = new Mock<IDependency>(MockBehavior.Loose);
which in turn is the same as:
1: var dependency = new Mock<IDependency>(MockBehavior.Default);
If you want to use strict mocks:
1: var dependency = new Mock<IDependency>(MockBehavior.Strict);
(Note that with Moq, to access the actual Mocked object, you need to access the .Object property. RhinoMocks doesn't require this because it uses extension methods).
Using Strict Mocks
So, now that we know how to create the two different types of mocks depending on the framework, let's take a look at a SUT and see where the problem with strict mocks lie. To make the post shorter, I'll use RhinoMocks, but you can accomplish the same with Moq.
Suppose we have the following class:
1: public class ServiceClass
2: { 3: private readonly IDependency _dependency;
4:
5: public ServiceClass(IDependency dependency)
6: { 7: _dependency = dependency;
8: }
9:
10: public void FirstMethod()
11: { 12: _dependency.FirstMethod();
13: Console.WriteLine("Called ServiceClass.FirstMethod"); 14: }
15:
16: public void SecondMethod()
17: { 18: _dependency.SecondMethod();
19: Console.WriteLine("Called ServiceClass.SecondMethod"); 20: }
21: }
and we want to test that when calling ServiceClass.FirstMethod, the corresponding call Dependency.FirstMethod is called, we could be tempted to do something like the following:
1: [Fact]
2: public void ServiceClass_FirstMethod_calls_dependency_FirstMethod_Strict()
3: { 4: MockRepository mocks = new MockRepository();
5:
6: IDependency dependency = mocks.StrictMock<IDependency>();
7:
8: using (mocks.Record())
9: { 10: dependency.Expect(m => m.FirstMethod());
11: }
12:
13: using (mocks.Playback())
14: { 15: ServiceClass serviceClass = new ServiceClass(dependency);
16:
17: serviceClass.FirstMethod();
18: }
19:
20: // Note that in the Record/Replay, VerifyAll is implicitly called
21: }
We've verified that Dependency.FirstMethod is called, everything passes, all is fine.
Welcome to BrittleVille
Two days later we get a change of request, that requires us to adjust the code for ServiceClass.FirstMethod. In particular, we need to call Dependency.ThirdMethod:
1: public void FirstMethod()
2: { 3: _dependency.FirstMethod();
4: _dependency.ThirdMethod();
5: Console.WriteLine("Called ServiceClass.FirstMethod"); 6: }
We check in the changes, run our tests, and boom! Test failed:
XunitException: Rhino.Mocks.Exceptions.ExpectationViolationException : IDependency.ThirdMethod(); Expected #0, Actual #1.
With strict mocks EVERY single call to the mocked object has to have expectations set on it. If we make an additional call and we don't set the expectation, our test will fail. Our test was to verify the FirstMethod was being called, and it still is. Our test failed because we wrote it using strict mocks, it failed for the wrong reason, and made our code very brittle.
However, if we were to have written the test using Dynamic mocks, this wouldn't happen:
1: [Fact]
2: public void ServiceClass_FirstMethod_calls_dependency_FirstMethod_Dynamic()
3: { 4: MockRepository mocks = new MockRepository();
5:
6: IDependency dependency = mocks.DynamicMock<IDependency>();
7:
8: using (mocks.Record())
9: { 10: dependency.Expect(m => m.FirstMethod());
11: }
12:
13: using (mocks.Playback())
14: { 15: ServiceClass serviceClass = new ServiceClass(dependency);
16:
17: serviceClass.FirstMethod();
18: }
19:
20: // Note that in the Record/Replay, VerifyAll is implicitly called
21: }
Note that out test is still valid. If we remove the call to Dependency.FirstMethod the test will fail as it should. However, it won't fail if we add additional calls.
An added bonus to using loose mocks with RhinoMocks, is that you can use the AAA (Arrange-Act-Assert) syntax and also call individual expectations. Thus the previous code could be written like so:
1: [Fact]
2: public void ServiceClass_FirstMethod_calls_dependency_FirstMethod_AAA() { 3:
4: // Arrange
5: IDependency dependency = MockRepository.GenerateMock<IDependency>();
6:
7: dependency.Expect(m => m.FirstMethod());
8:
9:
10: // Act
11: ServiceClass serviceClass = new ServiceClass(dependency);
12:
13: serviceClass.FirstMethod();
14:
15: // Assert
16: dependency.VerifyAllExpectations();
17:
18: }
Alternatively, if you don't need expectations to return values, you can just call AssertWasCalled on them:
1: [Fact]
2: public void ServiceClass_FirstMethod_calls_dependency_FirstMethod_AAA() { 3:
4: // Arrange
5: IDependency dependency = MockRepository.GenerateMock<IDependency>();
6:
7: // Act
8: ServiceClass serviceClass = new ServiceClass(dependency);
9:
10: serviceClass.FirstMethod();
11:
12: // Assert
13: dependency.AssertWasCalled( m => m.FirstMethod());
14:
15: }
Summary
Mocks are a great thing to test behaviour between different components. However, make sure you use them correctly if you don't want to end up with brittle code that any minor change breaks a whole bunch of tests. Strict and ordered mocking should only be used in exceptional cases.
Thursday, 2 April 2009 07:37 by
hadi
During sessions/workshops on MVC, I would say that 90%-95% of the attendees (yes I do "poll" the crowd, so it's based on facts), walk out liking MVC and realizing it's potential. However, there is one frequent question that I'm asked:
How do we know if Microsoft is going to continue to support ASP.NET MVC?
Personally I think that they will continue to support it, but I can't read the future (If I could, trust me, I wouldn't be blogging about it). However, yesterday's announcement changes things. Even, for the sake of argument, if Microsoft decide to discontinue MVC, who cares. They've made it Open Source. So tomorrow, any company (including your own) could pick it up and continue to support it. This should add extra guarantee for those in doubt of whether to invest or not into ASP.NET MVC.
On the other hand, if you're the kind of developer/shop that doesn't buy into Open Source, move right along, nothing to see here, business as usual. Or wait, maybe it's about time you realize that Open Source is not such a bad thing after all...
Congratulations Microsoft, Phil Haack & Co. Good move!