Syntax for mocking a method with a ref argument - c#

I have the problem that I can't mock a method that has a ref argument.
The signature of the method I want to mock away is as follows:
class ContractRepository
...
public long GetValueAndIncrement(ref Counter counter)
{
...
}
I tried to mock it like this:
Random myRandomizer = new Random();
var contractRepo = new SIContractRepository();
contractRepo.GetValueAndIncrementCounterRef = ((internalCounter) => Int64.Parse(myRandomizer.Next().ToString()));
But the compiler tells me that I am missing the "ref" keyword, but when I try it like this
Random myRandomizer = new Random();
var contractRepo = new SIContractRepository();
contractRepo.GetValueAndIncrementCounterRef = ((ref internalCounter) => Int64.Parse(myRandomizer.Next().ToString()));
I get an error that ref is an invalid expression
Unfortunately, google doesn't help here. :(
Any ideas?

You simply can't use anonymous methods in this case, because they support neither ref nor out parameters. You need to create a "real" method.
public void SetupMock()
{
Random myRandomizer = new Random();
var contractRepo = new SIContractRepository();
contractRepo.GetValueAndIncrementCounterRef = GetValueAndIncrementMock;
}
public long GetValueAndIncrementMock(ref Counter counter)
{
return Int64.Parse(myRandomizer.Next().ToString())
}

You can use anonymous methods with the ref keyword, just explicitly specify the type in the anonymous method:
(ref Counter internalCounter) => Int64.Parse(myRandomizer.Next().ToString())

Remember that the current version of Moles only supports ref and out arguments as the LAST argument of a method.
http://research.microsoft.com/en-us/projects/pex/molesmanual.pdf
Limitations
The current implementation of Moles has several limitations. These limitations are not
inherent to the approach and might be resolved in future releases of Moles:
 The Moles framework supports only a limited number of method signature—up to
10 arguments, where the last argument can be an out or ref argument.
Method signatures with pointers are not supported.
 Sealed classes or static methods cannot be stubbed because stub types rely on
virtual method dispatch. For such cases, use mole types as described in “Mole
Types” later in this document

I am not sure whether this is a correct way to apply moles but I did it. And it works.
///method get call in unit test
public static void DetermineSprintCorporateLiableCustomer()
{
COptions p2 = new COptions();
MGetCOptions.CustomerInfoCallerOptionsRef = (ref COptions p1) =>
{
if (p1 != null && p1 != null && p1.Type.Equals(
"Data", StringComparison.OrdinalIgnoreCase))
{
p1.Type = "P";
p1.Indicator = true;
}
p2 = p1;
};
}
When this part executed during test run, new p2 is available. Below was my scenario.
// need to unit test Coptions.Type="Data"
public static MainMethod(Coptions)
{
Mclass.Method(ref Coptions);
If(COptions.Type="B")
Do something();
}
It works with new value but there could be a better way.

Related

C# static inline method parameter

For performance reasons, I'm trying to reduce the overhead of having a new instance of a reference type created every time a particular method is called.
As a basic example:
public int AccumulativeCount(Expression<Func<int>> exp)
{
// usually do something useful with "exp". Instead put a
// breakpoint and get the memory reference of exp via "&exp"
return 1;
}
When it is called elsewhere in the code, the reference of exp in the AccumulativeCount method is different:
AccumulativeCount(() => 7);
Is there a way to make the parameter from the calling code static inline? In the example above the parameter "() => 7" is obviously never going to change, so there is no compelling reason why it should be recreated every time.
I'm aware that I could change the calling code to be:
public static Expression<Func<int>> MyStaticCountExp = () => 7;
// ... later in the code
AccumulativeCount(MyStaticCountExp);
The reason why I'm against the above is the expression only makes sense in the context that it is a parameter for. Also the code is not as clean as it could be. Is there something like:
AccumulativeCount(static () => 7); // does not compile
I don't know exactly your usecase, but maybe the Lazy<T> class will help.
public static readonly Lazy<int> Something = new Lazy<int>(() => AccumulativeCount(() => 7));
public static int AccumulativeCount(Expression<Func<int>> exp) {
// usually do something useful with "exp". Instead put a
// breakpoint and get the memory reference of exp via "&exp"
return 1;
}
public static void DoSomething() {
// the value was not available, so the AccumulativeCount(...) will be called
var a = Something.Value;
// the value is already created, no more call of AccumulativeCount(...) is needed
var b = Something.Value;
var c = Something.Value;
var d = Something.Value;
}

Moq an indexed property and use the index value in the return/callback

I want to moq a property that has an index, and I want to be able to use the index values in the callback, the same way you can use method arguments in the callback for moq'd methods. Probably easiest to demonstrate with an example:
public interface IToMoq
{
int Add(int x, int y);
int this[int x] { get; set; }
}
Action<int, int> DoSet = (int x, int y) =>
{
Console.WriteLine("setting this[{0}] = {1}", x, y);
throw new Exception("Do I ever get called?");
};
var mock = new Mock<IToMoq>(MockBehavior.Strict);
//This works perfectly
mock.Setup(m => m.Add(It.IsAny<int>(), It.IsAny<int>()))
.Returns<int, int>((a, b) => a + b);
//This compiles, but my callback never seems to be called
mock.SetupSet(m => m[It.IsAny<int>()] = It.IsAny<int>())
.Callback(DoSet);
var obj = mock.Object;
Console.WriteLine("Add(3,4) => {0}", obj.Add(3, 4)); //Works perfectly
obj[1] = 2; //Does not throw, why?
Edit: To clarify, I want the callback/returns method for the get to be Func<int,int>, and the callback/returns method for the set to be Action<int,int>. Trying what Mike suggested, you can sort of do this for set, but with one major limitation:
mock.SetupSet(m => m[23] = It.IsAny<int>())
.Callback(DoSet).Verifiable();
The callback DoSet is indeed then called with values (23,<any>). Unfortunately, using It.IsAny<int>() instead of 23 seems to behave as 0, rather than <any>.
Also, I couldn't find a way of calling SetupGet with Returns where Returns takes a Func<int,int> that would even compile.
Is it possible to use Moq for this?
Motivation: I'm just playing with Moq, attempting to use it to provide a fluent API for performing interception. That is, given an interface I and an instance X of I, automatically create a Mock<I> proxy with behaviour defaulting to X.
Would probably make more sense to work directly with Castle DP, but I like the Moq Expression Tree syntax.
The method SetupSet takes a plain delegate, not an expression tree of type Expression<...> like many other Moq methods.
For that reason Moq cannot see that you used It.IsAny. Instead, It.IsAny is called (not what we want) and Moq sees its return value only which happens to be default(int), or 0.
As of Moq 4.2.1502.0911 for .NET Framework 4.5, I found the following behavior to be true.
The problem you're running into is specifically due to the It.IsAny<T> call. If you use It.IsAny<T>, the callback does not execute:
[Test]
public void DoesNotExecuteCallback()
{
// Arrange
var mock = new Mock<IIndexable>();
var called = false;
mock.SetupSet(m => m[It.IsAny<int>()] = It.IsAny<int>()).Callback<int,int>((x, y) => called = true);
var instance = mock.Object;
// Act
instance[1] = 2;
// Arrange
Assert.That(called, Is.False);
}
But if you call it using specific parameters, it calls the callback:
[Test]
public void DoesExecuteCallback()
{
// Arrange
var mock = new Mock<IIndexable>();
var called = false;
mock.SetupSet(m => m[1] = 2).Callback<int,int>((x, y) => called = true);
var instance = mock.Object;
// Act
instance[1] = 2;
// Arrange
Assert.That(called, Is.True);
}
To summarize, you should avoid the use of the It.IsAny when trying to setup expectations for an indexer. In general, you should be avoiding the use of it because it can encourage sloppy test writing
There are appropriate use cases for It.IsAny, but without knowing the specifics I tend to recommend against it.

Ambiguous call of method

I have the following code
class Program
{
static void Main()
{
A a = new A();
a.M(null);
}
}
class A
{
public void M(int? i)
{ }
public void M(string s)
{ }
}
And I have an error, because the call is ambiguous. I need to change the call of M method without adding any lines to Main method and accessing class A so that it became correct. Could someone please tell me how to do this?
You can use explicit cast:
A a = new A();
a.M((string)null);
or
a.M((int?)null);
to help the compiler of picking the right overload. Note that C# compiler can't determine what method overload to call based on null literal.
For advanced topic consider Eric's article What is the type of the null literal?
edit:
since your argument names are different, you can use named arguments, which are avaliable since C# 4.0:
a.M(i : null);
or
a.M(s : null);
You can use a cast, or the default keyword, or for int?, new int?() (which, due to how Nullable types work, is also the same as null). You could also use named parameters to disambiguate. Or, of course, if you were ok with adding another line, you could declare your value in a variable and pass that in.
// these call the int? overload
a.M(default(int?));
a.M((int?)null);
a.M(new int?());
a.M(i: null);
int? i = null;
a.M(i);
// these call the string overload
a.M(default(string));
a.M((string)null);
a.M(s: null);
string s = null;
a.M(s);
The answer is that you cannot overload the member M this way if you cannot alter existing call sites.
Presumably you are adding one of the two methods and can alter the call sites for calls to the new method. Change the name of the method for those new call sites to use.

PrivateObject wont return out parameter

I'm trying to test private methods in a Unit test project. So far it's going great, but I hit a bump, when I have to test a method with an out parameter. The signature for that method is:
private bool GotSSI(out SSI ssi, RSI rsi)
{
~code omitted~
}
And the unittest (the part that is not working) looks like this:
SSI ssi = null;
object[] p = new object[]{ssi,rsi};
Type[] t = new Type[] { typeof(SSI).MakeByRefType(), typeof(RSI) };
actual = (bool) privateTarget.Invoke("GotSSI",t,p);
The GotSSI method work. I've tested it in debug mode within the unit test and I can see that the 'ssi' out variable is set inside the method, before returning it's true or false value. But when the test returns to it's own code, the 'ssi' variable is still null. So the problem is that the object I created in the "GotSSI" method, is not parsed out of the PrivateObject invoke method.
Anyone knows what I am missing?
Update (Solution by Rafal)
Rafal's solution work perfectly and here is how I implemented the solution.
I created a delegate:
delegate bool GotSSIInternal(out SSI ssi, RSI rsi);
And when I have created the object I wanted to test, I build the delegate (target is the object i'm testing):
GotSSIInternal gotSSIInternal = (GotSSIInternal) Delegate.CreateDelegate(
typeof (GotSSIInternal),
target,
typeof(OfflineResolver).GetMethod("GotSSI", BindingFlags.NonPublic | BindingFlags.Instance));
After that is very simple to call the delegate:
actual = gotSSIInternal.Invoke(out ssi, rsi);
The solution is very simple and works like a charm.
Although the final solution that was accepted works, there is a much simpler way to do it. If you follow the link given in the accepted answer from Rafal, you will find a similar question to this one, with two answers. The second answer (with the most "useful" points) is the simpler of the two.
Here is a modified version of that answer specifically for a testing scenario:
//method to test is a private method of the class ClassTotest with signature
// TryGetCustomerData(List<Invoice> invoices, out CustomerData customerData)
//set up
var objToTest = new ClassToTest();
var invoices = GetInvoices();
CustomerData customerData = null;
//set up the arguments
var args = new object[] { invoices, customerData };
//get the MethodInfo of the method you want to test
var method = typeof(ClassToTest).GetMethod("TryGetCustomerData",
BindingFlags.NonPublic | BindingFlags.Instance);
//invoke it
var success = (bool)method.Invoke(objToTest, args);
//get back the customerData argument - the "out" parameter
var actual = args[1] as CustomerData;
your invocation of method with out parameter is wrong if you want to get the out value. See this on how to invoke it with reflection.
You need to ask yourself if you really need to test private methods? I personally do not test Private methods but it is all down to personal opinion (and it can get quite heated). There are numerous reasons / articles / opinions. A good SO thread can be found here.
An excerpt from the accepted answer is "A private method is an implementation detail that should be hidden to the users of the class. Testing private methods breaks encapsulation..."
The reason I do not test my private methods is because they are more likely to change than the public interface. If you cover all of your private methods it makes refactoring more complex (again, just my opinion). If you change a private method and the Public interface breaks you will know as your unit tests fail and you can then drill down.
That is just my opinion and I know many disagree so just putting it out there!
I can use PrivateObject to do this, although it is not technically a "return value", like:
object[] p = new object[] { null, rsi };
Type[] t = new Type[] { typeof(SSI).MakeByRefType(), typeof(RSI) };
actual = (bool)privateTarget.Invoke("GotSSI", t, p);
SSI ssi = p[0];
Actually the type array can be omitted if the method overload can be determined without it:
object[] p = new object[] { null, rsi };
actual = (bool)privateTarget.Invoke("GotSSI", p);
SSI ssi = p[0];
Just do this: https://instance-factory.com/?p=738
ClassWithPrivateMethods instance = new ClassWithPrivateMethods();
PrivateObject privateObject = new PrivateObject(instance);
object[] args
= new object[] { "some value", null /* placeholder for out param */ };
privateObject.Invoke("PrivateMethodHavingOutParameter", args);
var outParameterValue = args[1];

Moq: How to get to a parameter passed to a method of a mocked service

Imagine this class
public class Foo {
private Handler _h;
public Foo(Handler h)
{
_h = h;
}
public void Bar(int i)
{
_h.AsyncHandle(CalcOn(i));
}
private SomeResponse CalcOn(int i)
{
...;
}
}
Mo(q)cking Handler in a test of Foo, how would I be able to check what Bar() has passed to _h.AsyncHandle?
You can use the Mock.Callback-method:
var mock = new Mock<Handler>();
SomeResponse result = null;
mock.Setup(h => h.AsyncHandle(It.IsAny<SomeResponse>()))
.Callback<SomeResponse>(r => result = r);
// do your test
new Foo(mock.Object).Bar(22);
Assert.NotNull(result);
If you only want to check something simple on the passed in argument, you also can do it directly:
mock.Setup(h => h.AsyncHandle(It.Is<SomeResponse>(response => response != null)));
An alternative is to use Capture.In, which is an out-of-the-box feature in Moq that lets you capture arguments into a collection:
//Arrange
var args = new List<SomeResponse>();
mock.Setup(h => h.AsyncHandle(Capture.In(args)));
//Act
new Foo(mock.Object).Bar(22);
//Assert
//... assert args.Single() or args.First()
Gamlor's answer worked for me, but I thought I would expand on John Carpenter's comment because I was looking for a solution involving more than one parameter. I figured other folks who stumble onto this page may be in a similar situation. I found this info in the Moq documentation.
I'll use Gamlor's example, but let's pretend the AsyncHandle method takes two arguments: a string and a SomeResponse object.
var mock = new Mock<Handler>();
string stringResult = string.Empty;
SomeResponse someResponse = null;
mock.Setup(h => h.AsyncHandle(It.IsAny<string>(), It.IsAny<SomeResponse>()))
.Callback<string, SomeResponse>((s, r) =>
{
stringResult = s;
someResponse = r;
});
// do your test
new Foo(mock.Object).Bar(22);
Assert.AreEqual("expected string", stringResult);
Assert.IsNotNull(someResponse);
Basically you just need to add another It.IsAny<>() with the appropriate type, add another type to the Callback method, and change the lambda expression as appropriate.
The Callback method will certainly work, but if you are doing this on a method with a lot of parameters it can be a bit verbose. Here is something that I have used to remove some of the boilerplate.
var mock = new Mock<Handler>();
// do your test
new Foo(mock.Object).Bar(22);
var arg = new ArgumentCaptor<SomeResponse>();
mock.Verify(h => h.AsyncHandle(arg.Capture()));
Assert.NotNull(arg.Value);
Here is the source for ArgumentCaptor:
public class ArgumentCaptor<T>
{
public T Capture()
{
return It.Is<T>(t => SaveValue(t));
}
private bool SaveValue(T t)
{
Value = t;
return true;
}
public T Value { get; private set; }
}
Gamlor's answer works, but another way of doing it (and one which I consider to be more expressive in the test) is...
var mock = new Mock<Handler>();
var desiredParam = 47; // this is what you want to be passed to AsyncHandle
new Foo(mock.Object).Bar(22);
mock.Verify(h => h.AsyncHandle(desiredParam), Times.Once());
Verify is very powerful, and worth taking the time to get used to.
You could use It.Is<TValue>() matcher.
var mock = new Mock<Handler>();
new Foo(mock.Object).Bar(22);
mock.Verify(h => h.AsyncHandle(It.Is<SomeResponse>(r => r != null )));
This also works:
Mock<InterfaceThing> mockedObject = new Mock<InterfaceThing>();
var objectParameter = mockedObject.Invocations[1].Arguments[0] as ObjectParameter;
Lot's of good answers here! Go with the out of the box Moq feature-set until you need to make assertions about several class parameters passed to your dependencies. If you end up in that situation though, the Moq Verify feature with It.Is matchers doesn't do a good job of isolating the test failure, and the Returns/Callback way of capturing arguments adds unnecessary lines of code to your test (and long tests are a no-go for me).
Here is a gist: https://gist.github.com/Jacob-McKay/8b8d41ebb9565f5fca23654fd944ac6b with a Moq (4.12) extension I wrote that gives a more declarative way to make assertions about arguments passed to mocks, without the drawbacks aforementioned. Here is what the Verify section looks like now:
mockDependency
.CheckMethodWasCalledOnce(nameof(IExampleDependency.PersistThings))
.WithArg<InThing2>(inThing2 =>
{
Assert.Equal("Input Data with Important additional data", inThing2.Prop1);
Assert.Equal("I need a trim", inThing2.Prop2);
})
.AndArg<InThing3>(inThing3 =>
{
Assert.Equal("Important Default Value", inThing3.Prop1);
Assert.Equal("I NEED TO BE UPPER CASED", inThing3.Prop2);
});
I would be stoked if Moq provided a feature that accomplished the same thing while being as declarative and providing the failure isolation this does. Fingers crossed!

Categories