Don't like visibility levels, change that
This came up with respect to MS MVC. The MS MVC team has decided to make some methods protected, and that makes testing using Rhino Mocks a bit of a pain.
Let us assume that I want test that the call to ProductController.Index() will render the "index.aspx" view. I can do something like:
[Test] public void ShouldAskToRenderTheIndexAspxView() { MockRepository mocks = new MockRepository(); ProductController controller = mocks.PartialMock<ProductController>(); using(mocks.Record()) { controller.RenderView("index.aspx"); // <<-- Compiler error here, RenderView is protected! } using (mocks.Playback()) { controller.Index(); } }
Problem, part of the Rhino Mocks design goal was the use of the compiler and tools as verifiers. I explicitly do not want to have strings in my code, and I put them only where I have no other choice. However, since Rhino Mocks by runtime subclassing, there is no issue with reflection calls...
This means that we can get around this limitation by using the following extension method:
public static void RenderView(this Controller self, string action) { typeof(Controller).GetMethod("RenderView").Invoke(self, new object[] { action} ); }
This is it, it will compile and work now.
Comments
Nice! I need to update my post with this technique.
Just one slight change is needed to the code. The RenderView extension method has to look like this since the original method is protected. But is is still a very neat technique. Seems like MVC is drawing out a lot of the cool stuff you can do with extension methods:
Could someone hint the guys at Microsoft that their code "protection" through internal/private/protected members all over the place might just not be such a good idea in the light of extensibility?
This may sound like blasphemy, but why doesn't Rhino mocks just add the ability to reference a method by name instead of having to call the method when registering it in the framework in order to handle non-public members.
I love the way it works for public methods, but if I need to add an extension method and then use reflection to wire up my mock I may as well be using the framework instead since I'll have the weakly typed issues anyway.
I would just feel dirty using extension methods in this way. Plus it seems like extra unnecessary steps every time you need to do something like this.
John,
I am accepting patches :-)
I'm a little into John's approach but with a twist.
Wouldn't it be possible to have Rhino mock expose all protected methods as public on creation of a partial mock
Certainly,
But you won't get the compile time access to that, RhinoMocks works at run time.
Just curious, would you recommend this mechanism over something like "Subclass and override"? For example:
public class TestController : Controller
{
}
Slightly more annoying, but with compile-time safety.
Haack has an interesting post on this topic:
http://haacked.com/archive/2007/12/09/writing-unit-tests-for-controller-actions.aspx
He recommends the Test Specific Subclass if you have protected methods. I think he implies in his post that most protected virtual methods will become public to assist TDD - which would ideally solve this problem.
Comment preview