Archive for March, 2009

How to Use Rhinos AssertWasNotCalled

At times in the testing process you want to make sure that a certain method on a mocked object _does_not_ get called. For example, perhaps you’re performing some validation on a object and the object fails the validation rules. At this point you’d want the call to pop back up the stack to the caller who can handle the proper validation violations.

An example of this is a class in the controller of an ASP.NET MVC app.  This controller performs the validation and if and only if everything is good will it call the Save method on the service layer (which then in turns does a whole bunch of other junk).

In my test I want to make sure my validation works and that messages are added to the ModelState Error collection  – this being a state based test. At the same time I also want to make sure that my service layers “Save” method is _never_ called. This is an interaction based test.

Here’s an example test:

[Test]
public void Controller_should_not_be_able_to_add_a_customer_with_a_empty_name()
{
    // Arrange
    var form = new FormCollection { { "FirstName", "" } };

    // Act
    var result = controller.Add(1, form);  // 1 is the customer id

    // Assert
    // State test
    Assert.That(controller.ViewData.ModelState["FirstName"].Errors.Count, Is.EqualTo(1));  

    // Interaction Test
    mockService.AssertWasNotCalled(x => x.Save(Arg<int>.Is.Anything, Arg<Customer>.Is.Anything));
}

 

In the code above we are wanting to make sure that the controllers FirstName error count is equal to 1 because we should not be allowing customers with empty names to enter our system. However, just because we captured an error message in the model state this does not mean that we have not mistakenly called the Save method on the service and accidentally saved the user in an invalid state. Therefore the following line prevents this test from passing if the service.save() method was called:

mockService.AssertWasNotCalled(x => x.Save(Arg<int>.Is.Anything, Arg<CustomerRecord>.Is.Anything));

 

Note the generic Arg<T> parameter. This allows me to tell Rhino Mocks that the argument can be any int value, and the customer could be any customer value. I don’t care which customer, Id, or etc it is, I _do_not_ want this method called whatsoever. I can also provide much more restrictive values with the generic Arg<T> as well, but at this level we’re capturing any possible value passed into the method. Essentially saying: make sure this method never gets called.

If that method is called, an ExpectationViolationException will be called: H

Rhino.Mocks.Exceptions.ExpectationViolationException: Expected that ICustomerService.Save(anything, anything); would not be called, but it was found on the actual calls made on the mocked object.

Happy mocking. (pun intended)

Castle ActiveRecord – NonUniqueObjectException

Ran into a small issue this morning. Posting the solution here should help me find it next time in a jiffy.

I was performing some database validation – I needed to ensure that x object with y name does not already exist in the DB before submitting it, and more stuff,  etc. I have to query the DB to see if this value exists or not. I’m using Castle Active Record and I’m using the Repository pattern to wrap my Active Record calls. I’m also utilizing the ActiveRecordMediator<T> class to help keep the AR (Active Record) DB calls out of the AR storage classes.

If everything was golden, I’d update the record using ActiveRecordMediator’s Update call. Otherwise some error handling took place. When the record was updated I had to hit the DB again. When this happened I got this exception:

 

NonUniqueObjectException: a different object with the same identifier value was already associated with the session

Oh boy. Fun.

Anyway, this seems to be a scoping issue as once my validation was occuring I was able to grab onto a record and then NHibernate cached that for me. Unfortunately when I went out of scope, NHibernate supposedly cleans up and gets rid of this cached object (from what I’ve read – if anyone had any more info on this please reply). However, later in the method call I perform a very similar call, and at this point the exception is thrown.

I fixed this by evicting the object directly after I used it. I just needed to check one value on the object and I never needed it again until (if and only if) I’d then update it.

The code to do this was as such:

ActiveRecordMediator<T>.Evict(instance);

Where the instance was the instance that i needed to cleanup.

After I performed an eviction from the session, the update worked perfectly.

Here is one link that helped me get started down this path to the solution.

Nine Questions with Me

I’ve known Chris G. Williams for awhile now and he recently asked me to partake in his awesome-ness known as “Nine Questions”. He’s been doing it for awhile now and has has some pretty notable names in his list. I’m proud now be a part of that list.

To read the nine question interview go here.

Thanks for having me on Chris. :)

A New Development Term: Blackfield Development

I’ve been through the trenches of the consulting world, the good the bad the ugly, I’ve had the the full time jobs, and the freelance work, etc, etc etc. I’ve experienced projects from the ground up, maintenance projects and projects that didn't even leave the whiteboard. During the years of participating in many projects I sometimes get to a point where I work on something so frustrating that I want to pull my hair out.I want to scream at the computer, yell obscenities then storm off and go have a drink at the local pub. I’ve noticed that this type of development is usually maintenance work or even new development on top of legacy code. Usually, this is known as Brownfield development.

Not today. Today is the beginning of a new era. Over the last few days I’ve dealt with one of these nightmare hair pulling out tasks that drive you up the wall. Upon thinking about it today I’ve decided that tasks that are centered around legacy code (again, brownfield development), yet drive you crazy beyond belief will now be known as …

BLACKFIELD DEVELOPMENT

Why “Blackfield” one might ask?

Blackfield development is the type of development where you’re given a task which is very similar to walking through a pitch black cave without a flashlight. You have to stumble, fall down, bang your head, cuss, scream, run into walls just to cross into the next chasm of pain. An example of this this kind of development: a client gives you a task and the code is so obscure that you cannot follow a single logical execution path. There are no unit tests, you cannot get it to compile or run half of the time and your deadline is tomorrow. The good news is that you have the team who wrote the original code sitting next to you. Don’t be fooled my friend, you are not in the clear yet … if you ask them a question – they don’t know the answer. Therefore you’re left stumbling down a pitch black cave of code nightmares that is full of binary monsters waiting to hop out of the screen and bite your face.

Yeah. Seriously… blackfield development – its serious business. Development so rough it hurts.

ASP.NET App – is not a valid Win32 application

Never seen this one before until this morning. Well, I’ve seen the “not a valid Win32 application” error a ton of times, but this is the first time on with an ASP.NET app (running MVC).

 

How to Fix

If you ever see this and your app is running IIS7, here’s the first thing to check:

  1. Inside IIS (7) click on Application Pools.
  2. Find the Application Pool that is configured for your web application in the list.
  3. Select it, then click Advanced Settings on the right.
  4. Second setting in the list: Enable 32-Bit Applications – must be set to True.

That should get you up and running again. I have no idea how my app pool changed from 32 to 64 unless another dev accidentally changed it.

Why

The reason the 64bit setting wont work? Here’s what I’ve determined from my reading – On a 64-bit Windows machine the World Wide Web Publishing service does not support running 32-bit and 64-bit worker processes concurrently on the same server, which is what happened above.