Faking a call to an array for a particular index raises an exception

1.3k views Asked by At

Having the following unit test:

public interface ITestMe
{
    object[] Values { get; }
}

[Test]
public void Test ()
{
    var sut = A.Fake<ITestMe> ();
    A.CallTo (() => sut.Values[0]).Returns (4);

    Assert.That (sut.Values[0], Is.EqualTo (4));
}

results in the following exception:

System.InvalidCastException : Unable to cast object of type 'System.Linq.Expressions.SimpleBinaryExpression' to type 'System.Linq.Expressions.InvocationExpression'.
at FakeItEasy.Expressions.CallExpressionParser.Parse(LambdaExpression callExpression)
at FakeItEasy.Configuration.FakeConfigurationManager.AssertThatMemberCanBeIntercepted(LambdaExpression callSpecification)
at FakeItEasy.Configuration.FakeConfigurationManager.CallTo(Expression1 callSpecification) at FakeItEasy.A.CallTo(Expression1 callSpecification)

Or maybe I do not know how to specify a fake for an indexer?

1

There are 1 answers

4
Blair Conrad On BEST ANSWER

The problem arises from the fact that Values isn't an indexer. It's a property that returns an array.

An unconfigured Values will return a zero-length array (because arrays aren't fakeable). That's what's happening here, and ()=>sut.Values[0] would fail if it were ever executed (which FakeItEasy doesn't do).

So the real takeaway here is that since Values is an array, which is not fakeable (see What can be faked?), there's no way to have FakeItEasy choose a return value for a particular offset. The best that can be done is to have Values return an array of your choosing, as @CharlesMager suggests. For example:

var myArray = new object[100];
myArray[0] = 4;
myArray[50] = 17;
A.CallTo(() => sut.Values).Returns(myArray);