FakeItEasy ReturnsLazily with out parameter

2.2k views Asked by At

I'm new to using FakeItEasy and rather stuck at my first attempt. The interface i want to fake has a method like this:

byte[] ReadFileChunk(string path,int offset,int count,out long size);

I would like to see how the arguments are passed on, so I'm using ReturnsLazily. Here is my attempt:

long resSize;
A.CallTo(() => dataAttributesController
     .ReadFileChunk(A<string>.Ignored, A<int>.Ignored, A<int>.Ignored, out resSize))
     .ReturnsLazily((string path, int offset, int count) =>
        {
             return Encoding.UTF8.GetBytes("You requested: " + path + "(" + offset + "," + count + ")");
        })
    .AssignsOutAndRefParameters(123);

This compiles, but when ran it generates this exception:

The faked method has the signature (System.String, System.Int32, System.Int32, System.Int64&), but returns lazily was used with (System.String, System.Int32, System.Int32).

Which is correct, but i can't figure out how to add the out parameter. If I change the ReturnLazily part to this:

.ReturnsLazily((string path, int offset, int count, out long size) =>
   {
      size = 0;
      return Encoding.UTF8.GetBytes("You requested: " + path + "(" + offset + "," + count + ")");
   })

it will not compile, and I don't understand the errors:

error CS1593: Delegate 'System.Func<FakeItEasy.Core.IFakeObjectCall,byte[]>' does not take 4 arguments
error CS1661: Cannot convert lambda expression to delegate type 'System.Func<string,int,int,long,byte[]>' because the parameter types do not match the delegate parameter types
error CS1677: Parameter 4 should not be declared with the 'out' keyword

For a novice like me, this reads like it doesn't like 4 parameters nor understands what to do with 'out'. Can someone please explain me how I should be reading these errors? A working example would be very welcome as well :-)

Thanks a lot!

--- EDIT ---

This seems to work:

A.CallTo(() => dataAttributesController
    .ReadFileChunk(A<string>.Ignored, A<int>.Ignored, A<int>.Ignored, out resSize))
    .ReturnsLazily(x =>
           Encoding.UTF8.GetBytes("You requested: " + x.Arguments.Get<string>(0) + "(" + x.Arguments.Get<int>(1) + "," + x.Arguments.Get<int>(2) + ")"))
    .AssignsOutAndRefParameters((long)123);

A bit less readable then I was hoping for, is this anywhere near the intended use of ReturnsLazily?

2

There are 2 answers

0
Blair Conrad On

Update: the issue I mention below was fixed in FakeItEasy release 1.15, so update to the latest version and you shouldn't have to worry about the out/ref specifiers on the methods when using ReturnsLazily.

Sorry for the delay. I'm glad you found a solution that at least functions for you.

I agree that the syntax you landed on isn't the most readable, but it does appear to be the correct one. The "convenience" versions of ReturnsLazily won't work with out/ref parameters because the lambda can't take the out/ref modifiers.

It doesn't help you today, but I've created FakeItEasy issue 168 to deal with the problem. If you have additional opinions, please drop by and comment or something.

0
philippdolder On

Is that interface under your control?

byte[] ReadFileChunk(string path, int offset, int count, out long size);

if so: Isn't out long size just the same as the size of the returning byte[]? In that case I would just remove the size parameter from the interface method and use the "nice-to-read" ReturnsLazily method as you intended first.