Using the Should assembly for testing

Posted by Joe Wilson on Monday, August 23, 2010 7:30 AM

Should is a .NET assembly of extension methods for building easy to write and easy to read assert statements.  The advantage of using this assembly is the syntax is more clear and more like human language.  It's free, open source, and it doesn't matter if you're using NUnit or MSTest or any test runner (Test Driven .NET, ReSharper, etc.).  The project is in Beta 1.1, but I've used it on a couple of projects now with no problems.

I've never really liked the MSTest way of doing an assert.  The whole expected and actual arguments always seemed flipped around to me.

// Assert
Assert.AreEqual("eggs", breakfast.Foods.First());
Assert.AreEqual("bacon", breakfast.Foods.Last()); 

Instead, just reference the Should assembly and add the

using Should;

statement to the top of your test code and you can change it to:

// Assert
breakfast.Foods.First().ShouldEqual("eggs");
breakfast.Foods.Last().ShouldEqual("bacon");

I think one of the tricks to writing good tests is to have code that is dead simple to read when you come back to it much later.  The Should assembly gives you that.

Here are some other calls from the CodePlex home page for the project:

        public void Should_String_assertions()
        {
            var obj = new object();
            obj.ShouldBeInRange(1,2);
            obj.ShouldBeNull();
            obj.ShouldBeSameAs(new object());
            obj.ShouldBeType(typeof (object));
            obj.ShouldEqual(obj);
            obj.ShouldNotBeInRange(1,2);
            obj.ShouldNotBeNull();
            obj.ShouldNotBeSameAs(new object());
            obj.ShouldNotBeType(typeof(string));
            obj.ShouldNotEqual("foo");
           
            "This String".ShouldContain("this");
            "This String".ShouldNotBeEmpty();
            "This String".ShouldNotContain("foobar");
            
            false.ShouldBeFalse();
            true.ShouldBeTrue();

            var list = new List<object>();
            list.ShouldBeEmpty();
            list.ShouldNotContain(new object());

            var item = new object();
            list.Add(item);
            list.ShouldNotBeEmpty();
            list.ShouldContain(item);
        }

You should check it out!

Tags:
Categories: Technical


kick it on DotNetKicks.com shout it on DotNetShoutOut

Don't mock HttpContext

Posted by Joe Wilson on Thursday, August 19, 2010 6:40 PM

He doesn't like to be mocked!crying kid

It's so easy to take a direct dependency on HttpContext and not even realize it.  If you're in the code behind in Web Forms or in a controller action in MVC, it's just right there, tempting you to use it to access session variables, application security, etc.

But don't.

Some little known facts about HttpContext:

  • HttpContext is the largest object ever created by humans.
  • If you printed out the code for everything in HttpContext, the pages could be stacked end to end to wrap around the Earth's equator 7 times.
  • Mocking HttpContext is like trying to calculate the last digit of pi.  There is always a little more to it. 
  • Chuck Norris gave up trying to mock HttpContext.  He was deep in HttpContext.Response and quit, curled into a ball on the floor, and started whimpering.

Sealed what?  Object reference what?

Let's say you've got some MVC security stuff you're trying to work with in a controller action.  You've got code like:

    public class OrderController : Controller
    {
        [Authorize]
        public ActionResult Process()
        {
            if (User.IsInRole("Admin"))
            {
                return View("SecretAdminStuff");
            }

            return View("NotAuthorized");
        }
    }

See that User.IsInRole() code?  That call is really to HttpContext.Current.User.IsInRole().  You just took the bait and are tied to HttpContext now.

So what? You have to use HttpContext to get that information, right?  Sure, but you don't want to be tied directly to it or you've created untestable code.

Let's try a couple tests to verify the branching in this action method is returning the correct view based on the user's role.  I'm using NUnit, Rhino Mocks, and the Should assembly below.  Rhino Mocks has .Stub() and .Return() extension methods to set the expected return values for whether the user is or isn't in the Admin role.

        [Test]
        public void Should_return_NotAuthorized_view_when_not_Admin_user()
        {
            // Arrange
            var mockContext = MockRepository.GenerateMock<HttpContext>();
            mockContext.Stub(x => x.User.IsInRole("Admin")).Return(false);
            var orderController = new OrderController();

            // Act
            var result = orderController.Process() as ViewResult;

            // Assert
            result.ViewName.ShouldEqual("NotAuthorized");
        }

        [Test]
        public void Should_return_SecretAdminStuff_view_when_Admin_user()
        {
            // Arrange
            var mockContext = MockRepository.GenerateMock<HttpContext>();
            mockContext.Stub(x => x.User.IsInRole("Admin")).Return(true);
            var orderController = new OrderController();

            // Act
            var result = orderController.Process() as ViewResult;

            // Assert
            result.ViewName.ShouldEqual("SecretAdminStuff");
        }

As soon as we run the tests we see "System.NotSupportedException : Can't create mocks of sealed classes".  Oh yeah, HttpContext is sealed.  That won't work.

Hmmm.  Aren't there some new classes in System.Web.Abstractions for just this kind of thing?  Let's change HttpContext

var mockContext = MockRepository.GenerateMock<HttpContext>();

to HttpContextBase

var mockContext = MockRepository.GenerateMock<HttpContextBase>();

and see if that helps.

The new problem is: "System.NullReferenceException : Object reference not set to an instance of an object."  Mocking HttpContextBase isn't helping because the test isn't passing the mock context into the controller.  Every call in the action method to User.IsInRole() will always call the real HttpContext, which isn't created because the test is not running in the ASP.NET process.

You can get around this with Typemock Isolator, which goes beyond mocking and can intercept the next call to HttpContext.Current.User.IsInRole() and swap out a result, but isn't there a simpler way to do this without buying another product or waiting for better abstract classes to work with?

A better way

We can't test something tied to HttpContext like this.  We need another approach.  The one I favor is wrapping the calls we care about, delegating out to the untestable code in the wrapper class, then passing an interface to the wrapper class into the constructor of the class using it.

Here's the wrapping class I've created to access a few HttpContext current user values and the interface for the wrapping class:

    public class CurrentUser : ICurrentUser
    {
        public virtual string Name()
        {
            return HttpContext.Current.User.Identity.Name;
        }

        public bool IsLoggedIn()
        {
            return HttpContext.Current.User.Identity.IsAuthenticated;
        }

        public bool IsGuest()
        {
            return HttpContext.Current.User.IsInRole("Guest");
        }

        public bool IsAdmin()
        {
            return HttpContext.Current.User.IsInRole("Admin");
        }
    }

    public interface ICurrentUser
    {
        string Name();
        bool IsLoggedIn();
        bool IsGuest();
        bool IsAdmin();
    }

Now I need to update the controller to inject this dependency into the constructor so it can be mocked, and use a private field set in the constructor for subsequent calls to _currentUser:

    public class OrderController : Controller
    {
        private readonly ICurrentUser _currentUser;

        public OrderController(ICurrentUser currentUser)
        {
            _currentUser = currentUser;
        }

        [Authorize]
        public ActionResult Process()
        {
            if (_currentUser.IsAdmin())
            {
                return View("SecretAdminStuff");
            }

            return View("NotAuthorized");
        }
    }

Now we've got a testable action method.  I mock the CurrentUser with MockRepository.GenerateMock<ICurrentUser>, set its return value with the Rhino Mocks .Stub() and .Return() extension methods, and check for the expected results:

        [Test]
        public void Should_return_NotAuthorized_view_when_not_Admin_user()
        {
            // Arrange
            var mockCurrentUser = MockRepository.GenerateMock<ICurrentUser>();
            mockCurrentUser.Stub(x => x.IsAdmin()).Return(false);
            var orderController = new OrderController(mockCurrentUser);

            // Act
            var result = orderController.Process() as ViewResult;

            // Assert
            result.ViewName.ShouldEqual("NotAuthorized");
        }

        [Test]
        public void Should_return_SecretAdminStuff_view_when_Admin_user()
        {
            // Arrange
            var mockCurrentUser = MockRepository.GenerateMock<ICurrentUser>();
            mockCurrentUser.Stub(x => x.IsAdmin()).Return(true);
            var orderController = new OrderController(mockCurrentUser);

            // Act
            var result = orderController.Process() as ViewResult;

            // Assert
            result.ViewName.ShouldEqual("SecretAdminStuff");
        }

Hey, wait a sec.

If you're thinking to yourself: I've just tested the code in the action method and not whether HttpContext really works, you're exactly right.  The tests should cover the branching in the controller action and are unit tests.  They are not integration tests that check to see if HttpContext is returning the right values.

I'm OK with that tradeoff.  I know HttpContext works.  It's been around forever and it's in a System.<something> namespace, so I shouldn't be testing it. 

The real question is, do my login and roles and authorization settings work as expected in my application.  That calls for integration testing, and the easiest way to do that is click through those screens and see if it's working.  You can also automate this clicking around with Watin, or SpecFlow (which uses Watin internally to drive the browser).

Tags: , , , , , , ,
Categories: Technical


kick it on DotNetKicks.com shout it on DotNetShoutOut

Do we still need coding standards?

Posted by Joe Wilson on Tuesday, July 6, 2010 6:31 PM

The dark ages

I used to be really big on coding standards in the late 1990's.  It was so easy to slip into spaghetti code in classic ASP and VB6, and at the time, the best antidote was rigid standards and uncompromising code reviews. 

I was a hard ass about our coding standards.  Then, as now, the rationale was that coding standards would make the code easier to read and maintain in the inevitable and long maintenance phase.

The development process we used at the time was to stand around the white board and talk about the development tasks, then the developers would go off and separately code it up.  That was the other reason the coding standards mattered - we didn't want two code files to look totally different if written by different developers.

My teams used the naming conventions Microsoft came up with for Access/VBA/VB, including Hungarian notation prefixes, but a lot of the standards were about code comments, error handling code, whitespace and indenting, etc.

.NET comes on the scene

Fast forward maybe 5 or so years to the introduction of .NET and C#, and coding changed.  ASP.NET HTML didn't require <% %> tags anymore.  We could put the C# in code behind files and other project files.  We didn't need On Error anymore, we had Try-Catch.  XML comments seemed like a cool feature to show Intellisense drop downs for code you wrote in addition to framework Intellisense.

So we updated our coding standards to reflect the language and IDE changes, but they became more like guidelines instead of hard and fast rules.  By convention, we would avoid the spaghetti code just by keeping the right code in the right place.  Hungarian notation went away (slowly but surely).  The coding standards document was mostly reference code snippets and justifications for the conventions we used.  Code reviews became less common because it wasn't as big of an issue.

Today

A lot has changed since .NET first came out, and I code differently now.  I'm trying to make my code a lot more terse these days.  I'm a big fan of having clean, succinct, expressive code.  The fewer non-essential things on the screen to wade through, the better.  It's more readable and easier to refactor.

  • I could put Try-Catch blocks everywhere, but isn't it simpler to catch unhandled exceptions in one place.
  • I could add XML comments, but why?  It's either code in my same web project or a project that is owned by my solution.  I don't usually work on common library code where an assembly will be used across projects and Intellisense might be needed.
  • I don't put the variable type on the left side of the equal sign anymore and use "var" instead.
  • I've walked away from code regions and just order the items in the class file by convention.  ReSharper likes to put new fields under the last field declaration in the class, so region wrapping all the fields in a class with "#region Fields" just wastes time when refactoring to pull it back up into the region.

Not only has the way I code changed, but the tools have changed. ReSharper code cleanup templates and StyleCop warnings can be used to keep your team writing code in a style that you've all agreed on.  Just run the tool and have it clean up the code for you or flag code that doesn't meet the style guidelines.

Having tests around the code lets me refactor and use auto-code-cleanup tools freely.  I understand the project a little more fully every day, so I can rename my class, method, and variable names to be more descriptive and accurate without worrying about breaking code.

I'm also doing more pair programming these days, and this is a good way to enforce and socialize team coding styles.  It also means we don't have to refer to a coding standards document as often.  Since we're more story-focused, we're thinking more about the feature and less about coding style.  Taking ceremony code off the screen helps us keep that focus.

If I had to do it over

If I was going to write a coding standards document today, it would be more like a style guide to reflect my current less-is-more thinking, and I'd probably give my peers a ReSharper template to auto-clean their code as they go instead of a document to refer to.  StyleCop for ReSharper looks promising as a gentle background reminder of team coding styles.

What about your team?  Do you have a coding standards document people refer to?  Do you use tools to enforce standards/styles?

Tags: , ,
Categories: Technical


kick it on DotNetKicks.com shout it on DotNetShoutOut

Unit testing untestable code

Posted by Joe Wilson on Tuesday, April 6, 2010 1:44 PM

Let’s say you’ve got a static or sealed class, or a class with non-virtual members that your code needs to use.  You need to unit test your code, but you can’t get an instance of this class and/or you can’t mock it. 

There are two ways to go:

  1. Buy a tool that let’s you mock things like this, such as Typemock Isolator or the newly announced Telerik JustMock.
  2. Code around it.

Buy it

I’ve already compared Typemock Isolator ($799) to RhinoMocks (free).  Typemock Isolator works as advertised.  The biggest issue is the price.  It’s hard enough to get management approval for introducing external tools.  But when buy-in literally means BUY in, it’s even harder.

Build it

Don’t despair if you’re stuck with “code around it” and using free mocking tools!  If you can change the code that is static, sealed, private, non-virtual, etc. fix it that way.  That’s the best thing.

But if it’s in a legacy assembly you have to use, and you can’t just change the original code, use this simple technique. 

Here’s the untestable class we need to use.  It’s static, so we can’t mock an instance of it with Rhino Mocks.

public static class StaticSendOrderClass
{
    public static void SendOrderToAccountsPayable(Order order)
    {
        // Pretend code here...
    }
}

Here’s the new code you’re working on that uses this static class to process an order:

public class OrderProcessor
{
    public void ProcessTheOrder(Order order, bool useStaticClass)
    {
        if (useStaticClass == true)
        {
            StaticSendOrderClass.SendOrderToAccountsPayable(order);
        }
        else
        {
            // Notify accounts payable some other way
        }
    }
}

First, we need to create an interface with just the functionality we need from the untestable class.  Name the class and method(s) whatever makes sense for your app.  You’re not tied to the legacy code naming convention; this is your code now.

public interface INotifyAccountsPayable
{
    void SendOrder(Order order);
}

Next, create a new class to implement this interface and wrap the untestable code.  In the method calls in the new class, turn around and delegate the call to the untestable class.

public class NotifyAccountsPayable : INotifyAccountsPayable
{
    public void SendOrder(Order order)
    {
        StaticSendOrderClass.SendOrderToAccountsPayable(order);
    }
}

Now inject the new interface into the constructor of your new class as an argument.  You’ll also want to create a private field and set its value to the instance argument in the constructor.  Now you can swap out your old code that calls the untestable code, and instead use your new private field.

public class OrderProcessor
{
    private readonly INotifyAccountsPayable _notifyAccountsPayable;

    public OrderProcessor(INotifyAccountsPayable notifyAccountsPayable)
    {
        _notifyAccountsPayable = notifyAccountsPayable;
    }

    public void ProcessTheOrder(Order order, bool useStaticClass)
    {
        if (useStaticClass == true)
        {
            _notifyAccountsPayable.SendOrder(order);
        }
        else
        {
            // Notify accounts payable some other way
        }
    }
}

Now you’ve got a unit testable OrderProcessor class!  Mock the INotifyAccountsPayable interface with Rhino Mocks and inject that mocked dependency into your class under test.  Then you can verify the call was made as expected.

[Test]
public void Should_call_untestable_code_when_useStaticClass_is_set_to_true()
{
    // Arrange
    var mockNotifyAccountsPayable = MockRepository.GenerateMock<INotifyAccountsPayable>();
    var orderProcessor = new OrderProcessor(mockNotifyAccountsPayable);
    var stubOrder = MockRepository.GenerateStub<Order>();
    var useStaticClass = true;

    // Act
    orderProcessor.ProcessTheOrder(stubOrder, useStaticClass);

    // Assert
    mockNotifyAccountsPayable.AssertWasCalled(x => x.SendOrder(stubOrder));
}

Please note this is not testing the internals of the untestable, static code.  But you don’t need to worry about unit testing the internals of that code.  You don’t own that code.  Testing that is really an integration test, not a unit test.  Using this approach, you isolate your new code from an external dependency and keep all your new code testable.

Tags: , ,
Categories: Technical


kick it on DotNetKicks.com shout it on DotNetShoutOut

Increasing Testability

Posted by Joe Wilson on Sunday, March 7, 2010 4:30 PM

Testa-what?

I don't know if "testability" is a word, but if Bud Light can make up "drinkability", maybe it should be.  I'm talking about how pliant your code is to testing.  If you're doing TDD or BDD, the code you write is testable by definition. 

But if you're going the other way, and coding first or testing legacy code (any code not already under test), you've probably run into code that was hard to test and felt like giving up.  Some of the most common hurdles for testability are not coding to abstractions and not decoupling dependencies.  Here's how to get around that.

The problem

Here's a garden variety Order class with a ProcessOrder method:

public class Order
{
  public string FirstName { get; set; }
  public string LastName { get; set; }
  public string Email { get; set; }
  public decimal Total { get; set; }

  public bool ProcessOrder()
  {
    var result = false;
      
    // Validate order
    if (!string.IsNullOrEmpty(this.Email) && this.Total > 0)
    {
      // Send order confirmation email
      var emailService = new EmailService();
      var emailSendResult = emailService.SendOrderConfirmationEmail(this);

      if (emailSendResult == true)
      {
        // Do more order processing...

        result = true;
      }
    }

    return result;
  }
}

And here's the test:

[Test]
public void Should_return_true_when_using_good_order_values()
{
  // Arrange
  var order = new Order();
  order.FirstName = "Joe";
  order.LastName = "Wilson";
  order.Email = "real_email_address@volaresystems.com";
  order.Total = 123.00m;

  // Act
  // Watch out!  Don't run this or it will send real emails!
  var result = order.ProcessOrder();

  // Assert
  Assert.That(result, Is.True);
}

We need to call the SendOrderConfirmationEmail method in the EmailService class.  But if our test calls ProcessOrder, there is no way to avoid calling the live emailing method as it's coded now.

How can we test the logic in the ProcessOrder method without sending out a real email?

Code to Abstractions

First, we need to code to an abstraction of EmailService, not to the concrete class itself.  So let's create an interface around EmailService:

public interface IEmailService
{
    bool SendOrderConfirmationEmail(Order order);
}

Then change the EmailService class to implement this new interface.  Visual Studio 2008 and ReSharper make this easy. 

This will let us change our test later to use a fake version of IEmailService instead of the real one.

Decouple and Invert your Dependencies

The next problem is we're creating an instance of the EmailService class in the ProcessOrder method.  Anytime you use "new" in your code, you're probably introducing a dependency and reducing testability. 

The fix is to let the caller create the instance and tell the class or method being called which instance to use.  I am using a private field with constructor injection to set the field instance.  Note we're also now coding to the interface IEmailService instead of the instance EmailService.

Here's the full Order method using the private field to call the SendOrderConfirmationEmail method on IEmailService inside the ProcessOrder method.

public class Order
{
  private readonly IEmailService _emailService;

  public string FirstName { get; set; }
  public string LastName { get; set; }
  public string Email { get; set; }
  public decimal Total { get; set; }

  public Order(IEmailService emailService)
  {
      _emailService = emailService;
  }

  public bool ProcessOrder()
  {
    var result = false;
      
    // Validate order
    if (!string.IsNullOrEmpty(this.Email) && this.Total > 0)
    {
      // Send order confirmation email
      //var emailService = new EmailService(); // Created outside this class now
      var emailSendResult = _emailService.SendOrderConfirmationEmail(this);

      if (emailSendResult == true)
      {
        // Do more order processing...

        result = true;
      }
    }

    return result;
  }
}

Dependencies can be very hard to spot, but it's critical to tease them out of your code to increase testability.  They can even come from things as innocuous as DateTime.  If you're code relies on DateTime.Now, how will you write unit tests for your logic without changing your system clock when you run the test?  It's simpler to have the caller pass in the DateTime value and have the method do the calculations based on whatever value it is given.

Make a Fake

Now that we've got testable code, we can make a fake EmailService and update our test.

First, create the FakeEmailService class implementing the IEmailService we created earlier.  We need the SendOrderConfirmationEmail method to return true to simulate an email being successfully sent.

public class FakeEmailService : IEmailService
{
  public bool SendOrderConfirmationEmail(Order order)
  {
    return true;
  }
}

You could also use a mocking framework like Moq or Rhino Mocks for this, but a homemade fake is easy, too.

Now we're ready to update our test to use the fake and inject it into the Order constructor:

[Test]
public void Should_return_true_when_using_good_order_values()
{
    // Arrange
    var emailService = new FakeEmailService();
    order = new Order(emailService);
    order.FirstName = "Joe";
    order.LastName = "Wilson";
    order.Email = "real_email_address@volaresystems.com";
    order.Total = 123.00m;

    // Act
    var result = order.ProcessOrder();

    // Assert
    Assert.That(result, Is.True);
}

Last step

We've refactored the Order class so the caller sends the IEmailService instance to it.  That makes sense for the test, but what about the real code?

I typically use an IOC container like Structure Map or Castle Windsor to hold and resolve an in-memory dictionary of interfaces and class instances.  You wire it up at application startup and when you call something that needs IEmailService, it creates an instance of EmailService for you.

If you're working with legacy code and can't use and IOC container, you also can add a no arg constructor like this:

public Order() : this(new EmailService())
{
}

public Order(IEmailService emailService)
{
    _emailService = emailService;
}

Your legacy code keeps calling the no arg constructor like it used to, and any new code and your test code use the constructor with IEmailService dependency passed in.

Wrap up

If you code isn't testable, you won't test it.  If you're working with legacy code or writing tests after coding, you can use these techniques to pull out external dependencies so they can be faked for testing. 

You can have it all: testable code, unit tests around that code, and no broken legacy code.  Mmmm.Testability.Drink it in!

Tags: , ,
Categories: Technical


kick it on DotNetKicks.com shout it on DotNetShoutOut

Presentation: Unit Testing and Mocking with NUnit and Rhino Mocks

Posted by Joe Wilson on Sunday, February 28, 2010 2:57 PM

Thanks to the folks who came out for my talk on unit testing and mocking with NUnit and Rhino Mocks at the Rocky Mountain Tech Trifecta.  I really appreciate all the comments and questions.  I was also really stoked to hear it helped some of you get over that unit testing hurdle.

The slides and code can be downloaded here.

Tags: , ,
Categories: Presentations


kick it on DotNetKicks.com shout it on DotNetShoutOut

Specifying Args with Rhino Mocks

Posted by Joe Wilson on Wednesday, November 25, 2009 4:33 PM

The problem

I ran into a snag testing some code today with Rhino Mocks.  I was mocking calls to a repository and inspecting the repository method calls and arguments passed.

Everything started off pretty normal with the repository dependency injected into the class under test:

// Arrange
var repository = MockRepository.GenerateMock<ICustomerRepository>();
var passenger = new Passenger(repository);

// Act
passenger.CallTheMethodUnderTest(arg1, arg2);

In my Assert section, I needed to check that the correct repository methods were called with the correct arguments.  The catch was, one of the arguments was a class created within the method under test.  I thought I could create and assert the equivalent Customer in my test like this:

// Assert
var expectedCustomer = new Customer
                           {
                               CustomerID = "1234",
                               FirstName = "Joe",
                               LastName = "Wilson"
                           };
repository.AssertWasCalled(x => x.SomeRepositoryMethod(
    arg1, 
    arg2, 
    expectedCustomer));

The two Customer objects (in the test and in the method under test) had the same values, but of course, were not the same objects.  They were two different Customer objects that happened to have the same values.  So Rhino Mocks told me that my expected Assert wasn't met.

The answer

I knew Rhino Mocks could ignore arguments with

Args<T>.Is.Anything

But I knew what the values should be.  In fact, for this test, the values being passed into the repository calls were just as important as the calls themselves.

So I tried comparing the values of the two Customer objects instead of the objects themselves:

repository.AssertWasCalled(x => x.SomeRepositoryMethod(
    arg1,
    arg2,
    Arg<Customer>.Matches(c => 
        c.CustomerID.Equals("1234") &&
        c.FirstName.Equals("Joe") &&
        c.LastName.Equals("Wilson"))));

So close!  But now Rhino Mocks told me if I used Arg for one parameter, I'd better use it for all of them.  No biggie. I made the change and this worked:

repository.AssertWasCalled(x => x.SomeRepositoryMethod(
    Arg<int>.Is.Equal(arg1),
    Arg<int>.Is.Equal(arg2),
    Arg<Customer>.Matches(c => 
        c.CustomerID.Equals("1234") &&
        c.FirstName.Equals("Joe") &&
        c.LastName.Equals("Wilson"))));

Postmortem

The Arg statement let's you specify a type and tell Rhino Mocks you don't know or don't care about the value:

Args<int>.Is.Anything

You can also tell Rhino Mocks you know the type and what the value should be:

Args<int>.Is.Equal(7)

If you have a non-primitive type or complex assert, you can also inspect values with the Matches statement:

Arg<Customer>.Matches(c => 
    c.CustomerID.Equals("1234") &&
    c.FirstName.Equals("Joe") &&
    c.LastName.Equals("Wilson"))));

I realize the code in these tests is probably way too familiar with the code under test.  I prefer testing state over this kind of interaction testing where possible.  But this was a case where the code under test had a void return and didn't do much besides parse some values and call repository methods based on those values.

In times like this, I'm glad I have interaction testing to fall back on so I can verify my code is behaving the way it should.

Tags: ,
Categories: Technical


kick it on DotNetKicks.com shout it on DotNetShoutOut

Why bother writing unit tests?

Posted by Joe Wilson on Friday, July 10, 2009 5:57 PM

More developers are coming around to the idea of writing unit tests for their code.  But not everyone is sold.  Let's take a look at the arguments for just writing code and either manually testing or handing the app over to QA:

  • It takes too long to write unit tests.
  • This is really simple code.  I could see maybe testing something complex, but this is just a CRUD app.
  • Write my tests before my code?  Are you kidding me?  I've always done it the other way and it's worked out just fine.

Let's take these one by one and see if they are still valid.

Time Argument

It doesn't take long to run the test.  I think there is consensus there.  But writing units tests and writing code is more lines of code than just writing the code.  More lines = more time, right?

Sure, as long as manual testing is less than the automated testing over time.  Not just the first time, but for the lifetime of that code.

If I'm using your old assembly from 2004 or web service from last month, I want some assurances it still works the way it was supposed to.  If you knew the secret way to manually test it, but have forgotten it, I don't fully trust your code.  I have to spend time going over that code and testing it out myself.

Code with a lifespan longer than your memory and availability to manually regression test it benefits from having a suite of unit tests that can be run in milliseconds.

Simplicity Argument

"If the code is really simple, there is no point in writing unit tests."

This is a good point.  Unit testing can help work through complex code, but what if the code is really easy?

I agree that there isn't a need to bother testing setting and getting properties and methods that just call other methods.  And please don't spend time testing code that is part of the .NET framework or an assembly you bought.  That's a waste of time.

But if you're using test-driven development, you start with the functionality, not the implementation.  So you write tests that cover the important/core stuff in your requirements.  You don't bother testing properties and call wrappers, which are just technical artifacts of the important stuff you are coding.  If it's the important stuff, shouldn't it be covered with unit tests?

TDD = My World Upside Down

Mad Hatter "Writing test before writing code is crazy talk." I also have had a great career without doing this, so what's the point?

I agree it is crazy.  I also agree it's a 180 on the conventional wisdom.  And I completely agree that it's harder than just writing the code.

But here's where I depart from the TDD crowd.  If you're new to unit testing, I just want you to write unit tests to cover the critical code for now.  It might lead you to TDD at some point, it might not.  But it's not an all or nothing thing.  Let's just try to work in as many tests as we can and leave it there for now. How many tests do you need?  What code coverage levels are you shooting for?  That's up to you.  If you feel good showing the code to your peers and are happy to be held accountable for the quality of your code, you're probably done.

I'll make the case for TDD another time.  Just baby steps for now.

Tags: ,
Categories: Technical


kick it on DotNetKicks.com shout it on DotNetShoutOut

Image Details