Extending Issues

In this installment I’ll be extending our rather basic Issue domain class to include some extra properties. These properties won’t be the complete set I have in mind, but in the interest of incremental changes (and an amount to work to I can write about in one post), I’ll limit it. We’ll be adding three new properties, CreatedDate, AssignedTo and ReportedBy. The later two will require a new domain class: User. Here is the class diagram of what we intend to add:

First of all we’ll change our New_Success unit test to mock out a new repository called IUserRepository and check that the property bag has a list of users that we get from the new repository that can be used to set the issue’s ReportedBy and AssignedTo properties. You might also notice that I have changed the way we set repositories for controllers. We no longer use public property setters, but now we use the constructor. The cool thing about using Windsor is that we didn’t need to change any configuration. Anyway, here is our new test:

Again, this doesn’t build as User and IUserRepository do not exist. So lets add them in the same way we added the Issue and IIssueRepository. We also need to add the new constructor parameter to the controller and the other unit tests.

The solution builds again now but running the tests, 3 fail. The New_Success unit test fails because we haven’t added the code to the controller that populates the property bag. The two acceptance tests fail because we haven’t injected the new IUserRepository and so the controller cannot be created. Adding these few things now fixes all the tests.

Next on the list is a change to the New_RenderNewIssuePage acceptance test to ensure that a select control exists on the page for the “Assigned To” and “Reported By” user for the issue being created. Running this test fails as expected, so we add controls to the Issue/New.vm view as follows:

All the tests now pass again but we haven’t added the new properties to the Issue class yet. So we change the New_CompleteFormAndSubmit acceptance test to check for these properties. We haven’t stored any users yet (need to solve the test data problem) but for now we can test against the issue being set as unassigned and reported anonymously.

As expected the test fails, so we add the properties to the Issue class and modify the list view to display them:

Running the tests again fail, why? We are getting the following error message:

SqlDateTime overflow. Must be between 1/1/1753 12:00:00 AM and 12/31/9999 11:59:59 PM

This is because we are not setting the new CreatedDate property in the Create action. So lets add that and run the tests again. We get passed that error, but now the test is failing because the “Unassigned” and “Anonymous” text is not present, instead we have: $issue.AssignedTo and $issue.ReportedBy, this is because these properties are Users and they are set to null.

What we need now is a Helper. Helpers are a nice place to encapsulate your view UI formatting code and other such helper methods. Can you guess what’s coming? Yes a new unit test for our non-existent UI Helper:

Of course as we’ve seen before, this doesn’t compile. So we just add the new UIHelper class with an empty method called FormatUser. The solution builds now and the tests fail as expected. Once we add the implementation, these new tests now pass. Of course the New_CompleteFormAndSubmit acceptance test still fails, to fix it we need to register the helper with the IssueController and then use it in the view like so:

As you may have noticed above, I’ve also added a helper method for formatting dates. I won’t bore you with the details here but I followed the same process as the other helper methods above. We now have 8 tests that pass!

Test data for acceptance tests
From the above tests I can see that I haven’t tested the case of selected a user for either the “Assigned To” or “Reported By” fields in my acceptance tests. To do that I need some test data (i.e. a user to select) which I don’t currently have. I’ll have a think about this and see if I can find a good solution. I decided to add a new test for this case and for now, I populated the database with a test user and then created a new acceptance test which selects the first user in the select list (index 1) and then confirms that the name of the user selected is on the following page:

Of course this is only a reliable test if there isn’t already an issue in the list with the same user selected. So we need a better solution for test data.

To get this test to pass I had to make a few minor changes. The first was to change the select list names to include .id so they now should be issue.assignedTo.id in the tests and the views. I also needed to change the base class of the controller to ARSmartDispatcherController so I could use the ARDataBind attribute in the Create action:

Using ARDataBind allows MonoRail to automatically load up the nested objects (the users) from the database via ActiveRecord based on the id’s posted from the form. This loading only works if the select list control name ends in the primary key field, in this case Id.

We now have 9 tests passing (as long as there is a user in the database for the last test). So far so good.

One other job I’ve done in this round is replacing all the hard coded text in the views with resource strings. This is very easy to do and from experience best to put in from day one. To do this I just added a new resource file (.resx) to the web application for this controller and then added a reference to it in the controller class:

[Resource("strings", "PixelDragons.PixelBugs.Web.Resources.Controllers.IssueController")]

Then in the views for this controller, just use the syntax $strings.RESOURCE_NAME. Simple really.

Just a few minor housekeeping changes this time. I noticed that the unit test asserts had the expected and actual parameters the wrong way round, so I’ve swapped these. I’ve also added a FullName property to the User class. This property isn’t under the control of ActiveRecord, it just concatenates the users first name and last name for convenience.

That’s it for now, you can get the full source code from Google Code:

Url: http://code.google.com/p/pixelbugs
Svn Revision: r7


4 Responses

  1. Looking good, one thing though… It seems the web.config isn’t in the svn repo.

  2. Cheers Ben, I’ve added it at rev 8.

  3. Cool, one more thing, the references in the commons project are looking for GAC’d assemblies. I assume they should be looking in your libs folder instead?

  4. Oops, school boy error. I’ve made the change and this will be included in the next commit which I’m just finishing off.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: