.net and other musings

Ben Lovell, an agile developer living in the UK.

Category: TDD

Incremental development with Monorail: Part Seven

Since our last installment I slipped in a ninja-edit to one of the configuration files. This was to ensure that our sole service was marked as transient rather than the default Windsor lifestyle of singleton. This was pointed out to me by an eagle-eyed commenter and was an oversight on my part. So we’re now at rev10 and ready to roll once again!

In our last post we tidied up a few bits and improved our code-base rather than actually adding features as such. This time we’re going to move down into the persistence and start to drive out this notional layer.

We’re going to handle data access using the repository pattern. The repositories will work on our ActiveRecord entities ensuring they’re persisted to our database. We will introduce a new interaction between our service BlogPostService and the newly introduced repository interface IBlogPostRepository. Let’s get on and write a test:

71

The test above is fairly self-explanatory. We’ve introduced the IBlogPostRepository and we’re passing it into our BlogPostService which should then call the Save method passing our mapped post. We need to get rid of the red code and get the test passing, so first we must create our new interface, and then modify the service constructor:

72

73

We need to modify our other tests that construct the BlogPostService as they’re still assuming only a single argument constructor exists. As we have some duplication going on we’ll push this construction up into our setup code:

74

We should be able to run our tests in this fixture now:

75

As expected, since our BlogPostService doesn’t actually do much with our repository yet, we need to do some pretty minor tweaking to pass this test:

76

Let’s try again now:

77  Cool, let us try and run the whole suite including our integration type tests:

78

The integration tests are failing as we’ve yet to map the new dependency in our Windsor configuration. We can specify this now:

79

We still have failing integration tests though, so we need to add the BlogPostRepository specified in our configuration:

80

As you can see it doesn’t do much, but we just want our tests passing at this stage. Let’s run the whole suite of tests now:

81

Great, we have a working product once more. I’m going to finish here, as ever, the latest changes have been committed:

http://code.google.com/p/mr-blogengine/

Next time we’ll make our new repository more useful and finally hit the database!

Incremental development with Monorail: Part Six

We finished up in part five with a full suite of passing tests and our BlogPostService is slowly taking shape now. The next few posts will introduce persistence and validation but before we get started on these features, we have a little housekeeping to perform on our existing code.

First step is to build the Castle trunk and update our references to the latest versions. Secondly, we’ll incorporate a few changes suggested by Hammett.

After building and replacing our references with the latest Castle build I’ll run the tests as a sanity check before we proceed:

62

With that out of the way our first code change will ensure we play nicely with HTTP. It is considered good practice to ensure requests which update or create resources is carried out via POST – so we can modify our only PostController.Save action to ensure this is so but before we do this we’ll write a test:

60

Running our test produces the following:

61

We’ll modify our Save action now to ensure we only accept the POST verb:

63

We have added the AccessibleThrough attribute and explicitly specified that our action must only allow the POST verb. We’ll run our test again and make sure everything is working as expected:

64

The next step is to modify our add.vm view to use the helper methods to generate our form tags. We’ve done that and once again we’ll run our tests:

65

I’m noticing a little duplication creeping in to our integration tests that should be removed. Also, until now we’ve had to assume that a web server is running on a specific port on our development machine in order to run the integration tests. Through a little tweaking we can spin-up a temporary server in our test fixture setup code and host our test code there instead.

First we add the WebDev.WebHost.dll to our lib project directory and ensure we’re referencing this from the testing project. The next step is to create an app.config file in the testing project so we can configure where and from which port our testing server should be hosting from:

66  Now we add some setup code for the fixture:

67

We’ll also make sure we bring the server down when we’re finished:

68

Now ensure the VS web server is not running on the same port, then we can run our tests and make sure our latest changes work out:

69

Now, since we specify the web root and port through configuration, we should also use these configurable values to determine the URLs in our tests:

70

You can see our tests now call BuildTestUrl to determine the full URL where we’re hosting the development server. Neat. I’m sure when we add further integration fixtures we’ll extract class this, but for now we have a nice working set of tests and should remember the principle of YAGNI!

I’m going to cut this installment short here. In the next post we’ll get back into the swing of it and continue implementing features.

As ever, the latest code has been checked in and is available here:

http://code.google.com/p/mr-blogengine/

MVC Storefront

Rob Conery has been posting a series of screencasts featuring the development of an ASP.NET MVC based product catalogue. This is being carried out in a “TDD” like fashion. The interesting difference between his posts and mine (apart from the obvious fact that I’m lazy and haven’t screencasted… yet) is that he starts from the bottom of the stack and works upwards towards the UI where as I do the opposite.

Its interesting contrasting the two approaches not to mention the differences between the ASP.NET MVC framework and Castle Monorail way of getting things done.

Incremental development with Monorail: Part Five

Welcome back. In this post I’ll be getting our tests passing again and cleaning things up a little. We left off with a failing integration test:

42

I suspect this is due to the IBlogPostMapper dependency we introduced to our BlogPostService not being handled by the container. If we run in the browser we can confirm this is in fact true:

As we’ve yet to implement our IBlogPostMapper we must go ahead and do this before we can add the container configuration to pass our integration test. Lets bust out a test and get things rolling:

43

We have a few blanks to fill in in order to get this to compile and run:

  1. Make the DTO’s properties virtual so we can mock them. This is in preference to extracting an interface.
  2. Implement IBlogPostMapper.
  3. Add the necessary properties to the IBlogPost interface.

Lets go ahead and do this now:

44

IBlogPostMapper minimal implementation:

45 

The necessary modifications to IBlogPost:

46

Now we can compile and run our test:

47

Our BlogPostMapper implementation is throwing an exception so lets go back and take another step to try and pass our test:

48

BlogPost:

49

I’m pretty certain we’ve done enough to pass our test now. Lets have a go:

50

OK now lets focus on the full suite:

51

Our integration test is still bombing but as we’ve got a mapper now, we can go ahead and wire up our Windsor configuration and get things moving again:

52

We’ve added another configuration file: mapper.config and referenced this from the web.config. We shouldn’t need to do any more than this so lets run our full test suite:

53

Our full suite is passing now. Not bad for 5 minutes work! As usual the latest changes are checked in to the Google code project hosted here.

Now we have a full passing suite, in our next edition I’ll be moving down into the persistence and also incorporating a few modifications from Hammett. Stay tuned!

Incremental development with Monorail: Part Four

We finished up in the last instalment by moving down a layer into our newly introduced BlogPostService. Our tests are passing yet our application is still pretty lacking in the actual functionality department. To move things on a stage further we need to:

  1. Map from the AddPostRequestDto to our actual BlogPost aggregate root.
  2. Validate the BlogPost.
  3. Persist our new BlogPost.

We need to write another test to flesh out the interaction between our service and something that can map from the DTO to our BlogPost:

37

We’re now expecting the BlogPostService to accept the mapper in its constructor, and defining an interaction between the service and the mapper. Before we can get this to compile we need to make a few more changes to our test fixture:

37

We’ve modified an existing test to allow for our new dependency and performed some setup tasks. We’ve introduced the IBlogPostMapper and IBlogPost interfaces by way of our test. Running the test causes the compiler to choke so lets go ahead and implement what we need to pass the tests:

38

39

40

Lets go ahead and run our BlogPostServiceFixture tests:

41

Righteo, that went well. For the sake of completeness lets run our full test suite:

42

The integration test is failing as we’ve yet to wire up the BlogPostService dependencies in the container. Before we can do this we need to drive out the interfaces we’ve introduced. We’ll do that in the next post.

Incremental development with Monorail: Part Three

Part One
Part Two

In the last instalment we finished up with a suite of passing tests. However, we’ve yet to produce anything remotely usable so lets continue by reaching down further and driving out our services/persistence. We’ll start by writing the following test:

23

We’ve meddled with our test setup a little to introduce the MockRepository for mocking out our PostController’s new dependency on the IBlogPostService. Our test now calls the AddPost method on our service interface and sets up the resulting AddPostResponseDto. Running the test produces a bunch of compiler whinging so we best implement the newly introduced bits:

24

25 

26

These are the only changes and additions we’ve made in order for the tests to compile and run. Running our test now produces the following result:

27

As we’ve yet to modify the PostController.Save(…) call to include a call the newly introduced IBlogPostService dependency. Lets go ahead and do this now:

28

We’ve now included the call to our newly introduced service and we set the responseMessage if the response is signaled as successful. Lets run our test now:

29

It works, ship it! Actually no, again we’re pretty low on actual functionality right now. Remember we’ve yet to actually drive out any implementation of the IBlogPostService interface as yet and I expect that the acceptance test will fail horribly since we didn’t wire up the necessary container configuration either. Lets go ahead and run the whole test suite and see what gives:

30

In the brief moments the browser appears during the test we can see the following:

31

Hmm, as I predicted earlier our application fails to run due to the lack of proper container configuration. Before we can do this we need to implement the IBlogPostService interface somewhere. We need to write a failing test to begin our foray into the implementation of a BlogPostService:

32

Lets create the BlogPostService only performing the steps necessary to pass the test above:

33

Run the test:

34

Now we have a working BlogPostService we can now wire up our container configuration to pass the acceptance test:

35

Now running the full suite of tests produces the following:

36

Our tests pass!

That’s it for this post. I’ve checked in the latest changes to the repository. In the next post we’ll continue our efforts and begin to implement validation on our screen-bound DTO’s.

Google code hosted project: http://code.google.com/p/mr-blogengine/

Incremental development with Monorail: Part Two

Part one can be found here.

So in part one we had finished up at a failing test. Lets recap what this was:

14

And our failing test:

9

Our add view assumes that a Save action exists on our PostController. In attempting to make the test above pass, we will introduce this new action. However, this will be driven out from the PostController’s test fixture like so:

15

We’re faced with a bunch of unimplemented types and members shown in red thanks to Resharper’s error highlighting. As you can see from the test we’ve introduced the AddPostRequestDto and the three properties it exposes. Secondly we’ve introduced the Save action to the PostController that accepts our AddPostRequestDto. Our test then simply asserts that the correct response was set and that the postcreated view is displayed.

Our first step is the implementation of the AddPostRequestDto. Thankfully Resharper will perform this for us:

16 

We’ve added this new type to the Core project under a new Messages namespace and folder for organisation.

Lets now go ahead and implement the new Save action on the PostController:

17

As you can no doubt see, we’ve done only the simplest thing possible to pass the test. Lets run our tests and see the results:

18

Well our controller fixtures pass nicely. I’ve got a sneaky suspicion that our acceptance test might fail however:

19

The expected confirmation was not displayed! We can assume this is as we’ve yet to create the postcreated view and spat back the responseMessage from this. Lets go ahead and create the view now:

 20

If I run the test again, in the very short time the browser is visible I can see that we’re failing with an exception occurring during the Monorail binding. To fix this we need to derive the PostController  from Monorail’s SmartDispatcherController and add the DataBind attribute to the Save action’s only parameter:

21

So lets go ahead and run our whole test suite:

22

Sweet! How functional our application is at this stage is still pretty debatable but we’re getting there 🙂

Our next task is to actually step down a layer and introduce a service to handle our persistence. I’ve checked in the latest changes. Stay tuned for the next post.

The google code hosted project: http://code.google.com/p/mr-blogengine/