Pete On Software

RSS Feed

Archive for December, 2008

Intro to NMock

If you do Test Driven Development (TDD) for any amount of time and with any amount of serious effort you are going to run across a problem. Sometimes you can’t test one object without other objects being involved. Since you can’t properly test one object without isolating it, you need to fake or mock the others that you aren’t testing. The Wikipedia entry on Mock Objects discusses it in some more detail.

A good candidate for a mock are objects that return current information (and as such are hard to properly test) or objects that will make permanent changes to databases, for instance, and as such are also poor candidates for repeatable testing.

The first (and only) mocking framework that I’ve used is NMock. I chose it because my rule is “when in doubt, choose the product that is named ‘n’ and then what you are doing” (remember my NLog and NUnit posts?).

Examine the code below and my comments about what each section is doing.

This outputs the following to the output window:

However, check out the following code:

This returns the following exception:

One application of how that could be useful would be if you are testing your business tier to make sure that it does not call Save() on an object or into the DataTier more than one time per invocation. There are other options, as well. You can say Expect.AtLeastOnce or Expect.AtLeast(some int) or Expect.AtMost or Expect.Between or Expect.Never. The framework is so flexible. You can define how you want the mock object to behave depending on its inputs.

Examine the following code that makes the SavePost method return true if passed 1 and false if passed -1.

As you can see, NMock is flexible and can be very useful to a programmer who is doing unit tests. Next time, I’d like to take a look at Dependency Injection / Inversion of Control and how it can be used with Mocking to not only make your code flexible, but very testable.

Project Euler Problem Two

Last time, I began working on the Project Euler problems and I set out guidelines for myself that I would attempt the problem first in C# (that I’m most comfortable with) and then try to solve the problem in some new way. Last time, I used some of the LINQ extension methods that I hadn’t previously used before. Some solutions might be in F#, Ruby, Python, etc, and I might use each “new way” more than once (since 10 lines of code doesn’t make me an expert!).

I present Project Euler Problem Two. Here is the code for the C# solution using LINQ.



















































As I note in the comments, this is basically Bill Wagner’s solution to this problem. His solution was so ingenious and taught me some things about LINQ that I just had to work it in here. The compute Fibonacci method was created because other Project Euler problems in the future are going to use the Fibonacci sequence, so we should have a reproducible way to create the series. I like his use of the dictionary to be able to ask for any point in the series at any time and you will only have to compute as terms that you have not yet calculated. Caching is a good thing.

The thing that was new to me was the let keyword in the LINQ query. What Bill does is store the value of the current n into value and then says that we only want it if it is even. This allows only the even values to be used. The rest of the problem is very simple, but I just wanted to point out those two points of interest.

I also tried this problem in Ruby. You can go to an interactive ruby session in your web browser here. If you type in the following code, you can see that it also works as well.

There is nothing special about this code. No whiz-bang code maneuvers. Just straight forward Ruby code. I found it very helpful to test it out at the link above and see that it worked. What is funny to me (and will likely get me in trouble) is how similar the basics of Ruby are to VB (or just BASIC) in general. It is easy to pick up because it is familiar to so many people. It was a good introductory exercise into Ruby, however, so I thought that I would share it with you.

If you have any comments or questions, please feel free to leave me a comment here.