Chains are difficult to grasp, to develop and to understand. And some of them are even hidden, and therefore are not so easy to identify. So, what are they and what have they done to deserve a couple of blog post? Apparently it’s a complicated feature to master from both the developer and user perspective. So I thought I’ll clear the topic, top to bottom, until I, I mean WE, understand it better.
What are chains?
We use the term “chain” to describe a set of chained calls, where the return value of one method is the target where the next method is invoked on. And since describing it in words is to confusing enough, consider this simple chain:
1 <span class="kwrd">int</span> x = a.b().c();
As any compiler knows, this is equivalent to:
12 SomeClass temp1 = a.b();<span class="kwrd">int</span> x = temp1.c();
And chains can be nested, as can be seen in the following simple example:
1 <span class="kwrd">int</span> x = a.b().c(d.e(f.g().h(2,i.j()));
Chains in Natural Mocks
Setting an expectation on a chain, originally meant setting it on the last call. Basically we don’t care about the rest of the chains, and setting expectations on the beginning or middle doesn’t matter for the test. But it’s a bit more complicated. One of the new features in Typemock Isolator 4.2 clears a semantic issue. The Repeat and RepeatAlways methods now refer to the entire chain. For example:
12345678 <span class="kwrd">using</span> (RecordExpectations rec = RecorderManager.StartRecording()){<span class="kwrd">int</span> x = a.b().c();rec.Return(5).RepeatAlways();}<span class="kwrd">int</span> t = a.b().c(); <span class="rem">//returns 5</span><span class="kwrd">int</span> s = <span class="kwrd">new</span> SomeClass().c(); <span class="rem">// is not mocked, and returns its original value</span>
The Missing LINQ
How’s LINQ connected to chains? (yes, some pun IS intended). Well, when the compiler parses LINQ queries, it creates a long chain of calls, full of expression, expression trees and other vegetation, which compile to chains and nested chains. So when someone tries to mock a LINQ query, they get a lot of confusing error messages. The error comes from the current implementation which handles nested chains sub-optimally. More on this later.
The Next Chain Chapter
So we are working on a fix for the LINQ problem. My next post will be about the how Isolator interprets chains, the pitfalls, and how we are progressing on the path to resolution. Which, by they way is full of fun.