544

I have a method on an interface:

string DoSomething(string whatever);

I want to mock this with MOQ, so that it returns whatever was passed in - something like:

_mock.Setup( theObject => theObject.DoSomething( It.IsAny<string>( ) ) )
   .Returns( [the parameter that was passed] ) ;

Any ideas?

BartoszKP
  • 34,786
  • 15
  • 102
  • 130
Steve Dunn
  • 21,044
  • 11
  • 62
  • 87

4 Answers4

739

You can use a lambda with an input parameter, like so:

.Returns((string myval) => { return myval; });

Or slightly more readable:

.Returns<string>(x => x);
Jakub Konecki
  • 45,581
  • 7
  • 87
  • 126
mhamrah
  • 9,038
  • 4
  • 24
  • 22
  • 1
    Seems quite easy until you need to do this for a method with **7 arguments**... When I inspected `IReturns` in Moq, it defines `Returns` for **4 arguments at most**. Any easy way to get around that? /I mean except modifying Moq source/ – mizuki nakeshu Jun 26 '13 at 16:27
  • 18
    ok, it's defined for up to **9 arguments** in `Moq` v `4.0.0.0`. solved :) – mizuki nakeshu Jun 27 '13 at 14:59
  • 20
    @mizukinakeshu I'd consider a bit of a refactor on a 9 argument method as it sounds like the class/method is doing too much. Perhaps refactor the 9 parameters into a settings class or struct to help you later? – The Senator Feb 08 '15 at 21:36
  • @TheSenator Agree, I don't reacall already what this was about but I guess I was just hacking some unit tests together for already existing code I was not to modify, otherwise this number of arguments definitely calls for refactoring. – mizuki nakeshu Feb 09 '15 at 13:21
  • 52
    Just a note as this confused me: The string in `.Returns` refers to the input parameter(s) and not the values you are returning. – Jim Jul 31 '15 at 15:13
  • This is the same approach taken for when mocking add and remove methods on DbSet in EF6. – IbrarMumtaz Jul 06 '17 at 12:05
  • @TheSenator at a previous job we had a build failure because there was a signature change from 62 to 63 arguments! (It was a search method FWIW, but obviously in desperate need of a refactor) – stannius Oct 02 '20 at 15:05
379

Even more useful, if you have multiple parameters you can access any/all of them with:

_mock.Setup(x => x.DoSomething(It.IsAny<string>(),It.IsAny<string>(),It.IsAny<string>())
     .Returns((string a, string b, string c) => string.Concat(a,b,c));

You always need to reference all the arguments, to match the method's signature, even if you're only going to use one of them.

rosscj2533
  • 9,195
  • 7
  • 39
  • 56
Steve
  • 4,415
  • 1
  • 19
  • 30
  • 24
    This should be the accepted answer. This is exactly what you need to do. Anything else throws a "number of expected arguments" exception. – Chaim Eliyah Feb 18 '15 at 17:28
  • Yea, definitely allot easier to read and works with `ReturnsAsync` too! – Piotr Kula Feb 16 '17 at 09:54
  • 2
    This answer saved the day. Note (future readers), you can take it a bit further as well. .Returns((string a, string b, string c) => { string d = "wow"; return string.Concat(a,b,c,d); } ); – granadaCoder Mar 03 '17 at 19:53
  • 1
    Personally, this is a much better answer. I have very little knowledge of Moq but still I understood it immediately. – unrealsoul007 May 05 '17 at 05:45
  • 2
    For methods returning void I used .Callback((string a, Exception b, string c) => throw new Exception(b.Message)); – tymtam Jun 12 '18 at 06:51
  • The fact that I had to (and could) declare the variables in the lambda was completely new for me. I wrote (a,b,c) =>and not (string a, string b, string c)=> – Erik83 Apr 17 '23 at 13:51
96

The generic Returns<T> method can handle this situation nicely.

_mock.Setup(x => x.DoSomething(It.IsAny<string>())).Returns<string>(x => x);

Or if the method requires multiple inputs, specify them like so:

_mock.Setup(x => x.DoSomething(It.IsAny<string>(), It.IsAny<int>())).Returns((string x, int y) => x);
Niclas Lindqvist
  • 1,412
  • 2
  • 17
  • 24
William
  • 8,007
  • 5
  • 39
  • 43
0

For those who are not using Moq, there's a way with NSubstitute.

mock.Method(Arg.Any<string>(), Arg.Any<string>(), Arg.Any<string>()).Returns(callInfo =>
    {
         var arg1 = callInfo[0].ToString();
         var arg2 = callInfo[1].ToString();
         var argN = callInfo[n-1].ToString();
         return arg1 + arg2 + argN; //or whatever
    });
Adrián Alvarez
  • 329
  • 3
  • 10