Chains, part III: Extension Methods

This post continues the path of part I and II regarding chained method calls using Typemock Isolator. Today I’m going to throw extension methods into the fray. And there’s nothing better to start with than a great tradition – here’s another pun:

Expectation Identifica-chain

Let’s start with a simple call:

Isolator has a trinity of sorts when identifying expectations: Instance, method and return value. It’s more complicated than that, naturally, but let’s keep it simple for now. So in the former case the trinity is:

instance: a
method: “b”
return value: x

Now, let’s look at this differently. What if b() is not an instance method, but an extension method? In that case, it is really a static method, not an instance method. For static calls, Isolator uses null value for the instance. So the trinity would be:

instance: null
method: “b”
return value: x

Exten-chain Methods

Let’s say we have the canonical chain:

As we already know, this usually translates to:

Suppose that the method c() is really an extension method. It looks like its invoked on the return value of tempReturn, but it is actually a static call of the class of tempReturn. It looks like this:

If we see a static call in the middle of a chain it is grounds for a chain break – the return value of the former call (tempReturn) is different than the target of the current call (which is null). Refer to the chain rules here.

Suspen-chain of Disbelief

So we need to maintain the illusion of the chain, although it is not really a chain. Isolator identifies a call as extension method via reflection – the method contains an ExtensionAttribute. For a method like this, we examine the first parameter (which for extension method is the “this” reference), and compare it to the return value of the former call. If they are the same we have a chain, and if not – we have a chain break.

This is chaining, for now. Too many chain puns can be hazardous to your health.