Unit Test Mock and State Live Together

Unit Test is an art. There is no silver bullet for what to test, how to test, what tools to use. In my opinion, everything depends on the kind of projects, the maturity of the projects, and the skill of developers in the projects.

The Story

Given this piece of code. It is not a real production code nor production quality code. I made it up to demonstrate in this post.

This is not a design or best practice post. Let’s focus on the business logic and what/how to test.

There is an Account with 2 properties:

  1. IsClosed (true/false): If closed, cannot withdraw money.
  2. Amount (decimal): The current total amount left in the bank Account. The amount is reduced by the Withdraw method.

I keep the Account class pretty simple.

To manage an account, we have AccountManager. What it does are

  1. If the account is closed, nothing happens.
  2. If not closed, and the amount is null (to demonstrate the point that it is invalid withdrawn amount), throw ArgumentNullException.
  3. If all is valid, the account’s amount is reduced by the withdrawn amount.

How are we going to test that 3 expected behaviors?

The Analysis

I believe at this phase, we have to depend on the mind of the developer. First, we need to recognize what kind of test we should perform.

#1: Look like an interaction test. We want to verify a certain behavior: Nothing happens.

#2: Verify input valid which expects an exception to be thrown.

#3: Look like a state test. We want to verify the account’s state. Why? Because we do not really care how the money is withdrawn. We only care about the amount left.

The Technology

Let bring in the tools we know to test. At this phase, depend on organizations; size and kind of projects. I work on .NET stack. I will use MS Test + RhinoMock (for interaction test).

#1: When the account is closed, nothing happens.

The account class might have many properties (now or later), but I only care about “IsClosed” property.

The main point is at the “Arrange” phase. I expect these behaviors

  1. The “IsClosed” must be called
  2. The “Withdraw” must not be called. It means: Do nothing.

I am happy to see that test passed.

#2: Throw ArgumentNullException

I can use either Mock or real object at this test as far as ensuring the IsClosed is false.

#3: If all is valid, account’s amount is reduced by the withdrawn amount

At this test, I do not care how the system implemented. Given a valid account, and a valid amount to withdraw, my account must have the right amount left.

Be very careful, fellows. If you use mock here, you will end up with interaction test.

 

As I said in the beginning, unit test is an art. You have to research, learn about it every day. Watch other people do it. Make up your own mind. During my career, I found out that developers have a tendency to jump directly to “The Technologies” phase. “The Analysis” phase is very important.

Happy coding and write more unit test.

Leave a Reply

Your email address will not be published. Required fields are marked *

%d bloggers like this: