What is AAA?
NUnit and likes have been using it for years. The Arrange, Act and Assert (AAA) structure of a test is very convenient, readable and maintainable. Using AAA a test looks like that:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<span style="color: #000000;">[TestMethod]</span> <span style="color: #000000;"><span class="kwrd">public</span> <span class="kwrd">void</span> SimpleTest()</span> <span style="color: #000000;">{</span> <span class="rem" style="color: #000000;">// Arrange</span> <span style="color: #000000;">RealLogger logger = <span class="kwrd">new</span> RealLogger();</span> <span style="color: #000000;">logger.Count = 0;</span> <span class="rem" style="color: #000000;">// Act</span> <span style="color: #000000;">logger.Increment();</span> <span class="rem" style="color: #000000;">// Assert</span> <span style="color: #000000;">Assert.AreEqual(1, logger.Count);</span> <span style="color: #000000;">}</span> |
Why Change?
One of the semantic problems in both Reflective and Natural Mocks, is that an expectation has two meanings: The first is what you expect to happen, and therefore should be verified. The second is behavior – what should happen when the method gets called – the method can be ignored ( or mocked or stubbed, depending on your dialect), called, throw, etc.
What happens when you want to just ignore a method? Well, you set an expectation and then calls RepeatAlways. What you actually say is “I want to set a behavior, but I don’t want to verify the call was made”. Because an expectation also includes behavior, you need to write two sort-of contradicting lines.
Well, no more. The AAA structure allows the separation. Here’s a simple test, using the new AAA format:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<span style="color: #000000;">[TestMethod]</span> <span style="color: #000000;">[Isolated]</span> <span style="color: #000000;"><span class="kwrd">public</span> <span class="kwrd">void</span> VerifyStubWasCalled()</span> <span style="color: #000000;">{</span> <span class="rem" style="color: #000000;">// Arrange</span> <span style="color: #000000;">RealLogger fake = Isolate.Fake.Instance<RealLogger>();</span> <span style="color: #000000;">Isolate.WhenCalled(() => fake.Increment()).IgnoreCall();</span> <span class="rem" style="color: #000000;">// Act </span> <span style="color: #000000;">fake.Increment();</span> <span class="rem" style="color: #000000;">// Assert</span> <span style="color: #000000;">Isolate.Verify.WasCalledWithAnyArguments(() => fake.Increment());</span> <span style="color: #000000;">}</span> |
The Arrange part contains creation of instances and setting an expected behavior. In our case, WhenCalled() sets an Ignore behavior on the void Increment() method – basically stubbing the method. On the Act part, we exercise the code. That means, Increment() called, and based on the behavior we set, the call is ignored. Finally, in the Assert part, we’re verifying the method was called.
That’s it – slick, readable and expressive.
A Few Words About the Syntax
You’ve noticed by now we’re using the Lambda syntax in our APIs. That’s true. The new API is supported on .Net 3.5. But there are some minor changes from regular expressions (no pun intended): No matter what method you use, you don’t need to pass the parameters in the parenthesis.
In addition, the syntax is type-safe. Take a look at this:
The WillReturn clause identifies that fake.IntCall() returns an integer, and therefore will allow to enter only integer values.
Finally the default for WhenCalled is always – ignore, returning values, throwing exceptions. You don’t need to repeat the line for every occurance. The behavior for the method specified in WhenCalled is the default. And yes – we intend in the future to have repeats and conditional returns as supplements based on the method we’re calling. What we have for now is a simpler way to write tests.
Want to start unit testing? Take advantage of our 15-day FREE trial of Isolator Complete. Get it now.