Browse by Tags

All Tags » Rhino.Mocks (RSS)

Use Dependency Injection To Simplify Application Settings

We've all seen and written code that accesses data from our app.config or web.config file.  We'll throw some simple settings in there: <? xml version ="1.0" encoding ="utf-8" ? > < configuration > < appSettings > < add key ="enableLogging" value ="true" /> < add key ="startDate" value ="12/1/2010" /> < add key ="baseFee" value ="157.50" /> </ appSettings > </ configuration > And then we'll use the ConfigurationManager to pull the data out when we need it: public class Foo { public void DoSomething() { bool enableLogging = Convert.ToBoolean(ConfigurationManager.AppSettings[ "enableLogging" ]); DateTime startDate = Convert.ToDateTime(ConfigurationManager.AppSettings[ "startDate" ]); decimal baseFee = Convert.ToDecimal(ConfigurationManager.AppSettings[ "startingFee" ]); } } Now that Inversion of Control and Dependency Injection are part of my everyday development, I don't do it this way anymore.  It's messy and doesn't allow me to easily plug in different values during testing. These days, I create a simple interface for my application settings: public interface IApplicationSettings { bool EnableLogging { get; } DateTime StartDate { get; } decimal BaseFee { get; } } And create an implementation of this interface that pulls data from app.config: public class AppConfigSettings : IApplicationSettings { public AppConfigSettings() { this .EnableLogging = Convert.ToBoolean(ConfigurationManager.AppSettings[ "enableLogging" ]); this .StartDate = Convert.ToDateTime(ConfigurationManager.AppSettings[ "startDate" ]); this .BaseFee = Convert.ToDecimal(ConfigurationManager.AppSettings[ "startingFee" ]); }   #region IApplicationSettings Members   public bool EnableLogging { get; private set; } public DateTime StartDate { get; private set; } public decimal BaseFee { get; private set; }   #endregion } I register my types with my IoC container .  During production, dependency injection takes over and automatically gives me my AppConfigSettings instance.  For testing, I generate a mock IApplicationSettings.  And using these settings just got a whole lot cleaner: public class Foo { public Foo(IApplicationSettings applicationSettings) { } } Technorati Tags: .NET , IOC , Mocking , Castle Windsor , Rhino.Mocks

ASP.NET MVC + MVC Contrib + Unit Testing

One of the key benefits of the MVC (Model View Controller) pattern is a separation of concerns that leads to better testability.  Microsoft recognizes this and will automatically create a separate MS Test project when creating a new ASP.NET MVC solution.  While this gives you a nice head start, there's room for improvement.  While actions in the MVC pattern are simply methods on a class that can easily be called by MSTest (or any unit testing framework), most web applications have interactions with supporting objects such a Request (query string, form parameters, etc…), Response (cookies, content type, headers, etc…), Session, and more.  In a live environment, these objects come as a result of the HTTP request being processed by IIS.  In a test environment, you're isolating just your controllers and actions and you don't have IIS and an entire HTTP pipeline. We can use mocking to provide "pretend" implementations of all of these objects, but there's a lot to mock.  This is where the MVC Contrib project on CodePlex can really come in handy! MVC Contrib Test Helper The MVC Contrib project gets a lot of praise for the many benefits it brings when developing for ASP.NET MVC – numerous UI helpers, Model Binders, Controller factories, etc…  But it also contains a TestHelper library that makes unit testing your controllers much easier.  By utilizing Rhino.Mocks , the MVC Contrib TestHelper can create and initialize your controller with mocked instances of: HttpRequest HttpResponse HttpSession Form HttpContext and more! In this article, I'll utilize the MVC Contrib TestHelper library to fully unit test a simple ASP.NET MVC controller.  As with many small demos, it's totally contrived, but helps illustrate the principals. Scenario We're building an ASP.NET MVC project that has to accept submissions from speakers.  We'll be doing this in a "wizard-like" fashion.  The prospective speaker will first enter their personal information (first name and last name).  The next step will have them enter their submission information.  There will be a final review point and finally, the actual submission.  Since some speakers want to submit multiple talks, we'll re-display the speakers personal information if they start the wizard up again after submitting a talk. Design In this article, we're only going to deal with the first step: collecting the speakers personal information (first name and last name).  We'll save this information in the Session object and pull it back out if the speaker returns to the beginning of the wizard after submitting a talk.  Both the speakers first name and last name are required – the user can not continue if they aren't both filled in.  The action on the controller is the "Speaker" action.  The next step in the wizard is the "SessionDetails" action. Using the information above, we have 5 test scenarios to cover: If we run the "Speaker" action with nothing in the Session: The result should be a ViewModel which has no speaker first name/last name and we should return a "View" result to ASP.NET MVC. If we run the "Speaker" action with a first name/last name in the Session: The result should be a ViewModel which as the first name/last name from the Session and should return a "View" result to ASP.NET MVC. If we run the "Speaker" action and only send in a first name: We should save the first name to the Session, but we'll also add an error for the missing last name to the ModelState and return a "Redirect" result so ASP.NET MVC will go back to the "Speaker" action and give the user the chance to enter their missing last name. Do the same test as above, but for the last name. If we run the "Speaker" action and send both a first name and a last name: The first and last name should be saved to the Session object and a "Redirect" result should be returned that tells ASP.NET MVC to go to the "SessionDetails" action. Set Up Start up a new ASP.NET MVC project and make sure you select the option to create unit tests.  The default ASP.NET MVC project comes with a Home controller.  For simplicity's sake, we'll add our actions to that controller and add our tests to the HomeControllerTests class. First, let's create a class to maintain our speaker information.  Sure, it's only two pieces of information, but this is a sample.  In the real world, we'd probably have more than this and therefore, we'll use a class: public class SpeakerInfo { public string FirstName { get; set; } public string LastName { get; set; } } Test #1 We start by writing our failing test (red), we'll throw together enough production code to get the test to pass (green), then we'll implement our actual logic and make sure...

The Essence of Open Source

While doing catch-up reading on the Rhino.Mocks group on Google , I came across this thread about a problem someone was having with Rhino.Mocks.  What I thought was cool was the responsiveness of Ayende (the creator of Rhino.Mocks).  And I'm not singling him out (I hear he hates being put on a pedestal), but I'm highlighting the generic responsiveness that you are more likely to get with an open source project.  Here's a breakdown of the timeline: 8:12 PM – Original question posted about the issue. 8:38 PM – Ayende asks for clarification on the exact issue. 9:55 PM – Original poster shows sample code highlighting the issue. 11:02 PM – At the request of Ayende (@ 10:13 PM), the original poster creates a failing test case that shows the issue in Rhino.Mocks 11:34 PM – The bug is fixed and in the repository for everyone to download and use. Slightly over 3 hours from bug report to resolved issue.  That's pretty damn cool!  In many commercial applications, it can take 3 hours just to acknowledge your support request. Technorati Tags: .NET , Rhino.Mocks , Open Source