Tangled testing?

Last night I started on my POP3 client code. I didn’t know where to start; I wasn’t really in the mood, so I wrote a test… That got the ball rolling. As usual the test first thing left me with a nicely decoupled class to write. Now I’m in a bit of a quandary about how to mock up the server that I need to test the client against…

The point of the CPOP3Client class is to provide a programmatic way to send POP3 commands and receive the results, parse them and present them in a way that’s easy to manipulate programmatically. So we have a function called STAT() which makes a call to the server, parses the results and returns a StatResult which contains the number of messages on the server and the total size in octets. It will probably throw and exception if the call fails for any reason… All pretty straight forward stuff. My original plan was to make the client completely async, but I couldn’t write a test for it, so I decided I didn’t understand the problem enough and delayed that part of the work. A synchronous client will allow me to get the job done and I can go back to the async design when I understand what I want to do…

The client talks to the world via two interfaces. There’s an output stream interface which allows it to write text and an input stream interface that allows it to read lines of text. At first I thought that the testing could involve me simply comparing whatever the client had written into the output stream with whatever I expected it to write, and priming the input stream with a response for it to parse and then checking that it behaves in the correct way. I expect I’ll do this for some of the tests, but it means building more testing infrastructure.

What I’m considering doing is using the testing infrastructure that I already have for the server side tests and hooking that, and the real production server code up to the client. In effect I’d be testing the client by running it against the server with some simple input and output shims to link the two together. I can use all of the mock mailbox and message store stuff that I already have and look at the results from the client rather than the server. The server itself will act as the validator of the client’s commands and I just have to write the code to validate the parsed responses.

I like this idea, but it worries me a bit. If there’s a bug in the server then I’m writing a client that works because of that bug… This adds an element of risk, but I think it’s one I’m prepared to live with given the kick start this will give me…