Using RhinoMocks - can I fetch the parameters of a called function? I mean; can I get some of the unknown parameters from the function call out?
I have a mock, and I expect some function to be called on this. I know one of the parameters, but the other one is unknown as this comes from the class that uses the mock and calls a function on it. More specificly - in this case - the unknown argument is a lambda function. This is a callback function that is supposed to be called when the function is finished executing. As the mock prevents the callback from being called I want to fetch it and call it myself.
So; I want to check that the function was called. I want to make sure some of the arguments were the expected ones. And I want to get out the unknown arguments to do some operations on them afterwards.
Assuming both arguments are ints (for simplicity) I'd like to do something like this:
int unknownInt;
_fakeSomething.AssertWasCalled(factory => factory.Foo(1, out unknownInt));
// then play around with unknownInt..
Can this be done? I see there is an Arg.Out, but couldn't quite make it work..
Note: Updated the question as it seemed to be misleading.
Arg<string>.Matches(arg => you got the argument here...);
UPDATE:
To fetch the second argument made on the first call of the Foo method on _fakeSomething:
string someArg = null;
var args = _fakeSomething.GetArgumentsForCallsMadeOn(
x => x.Foo(0, 0),
x => x.IgnoreArguments()
);
var int = (int)args[0][1];
Not sure if it can be done, but testing like that can result in unreliable tests, as you don't know the actual paramter that was passed in.
If possible, test on explicit data. If you f.eks pass in null instead of a real value your test will likely pass for the wrong reason.
Testing with Arg.Is.Anything should be done carefully and when you truly don't care about the parameter, such as in AssertWasNotCalled.
Related
I have hundreds of functions, each with different names and parameters. Every time a function is called, I need to log the method name, the parameter names and the values which the client passes in via the parameters. But I don't want to write the logging code for every function. It takes a long time, and every time a function's parameters are changed the logging code needs to change too.
So I hope I can write one block of code, and insert it into the beginning of every function. This block of code uses reflection to get the method name, names of the parameters, and most importantly, the values passed into the function via the parameters.
How do I do that?
Getting the method name is easy via [CallerMemberName] on a helper function like:
static string Me([CallerMemberName]string caller=null) => caller;
Getting the MethodInfo, and thus the ParameterInfo definitions (including the names) is pretty easy, but not very efficient. Getting the parameter values is not a thing you can do with the reflection API, and even if it could: the performance would be catastrophically bad. Since you say
and most importantly, the values passed into the function via the parameters.
I think you need to look at alternatives. One of which might just be "add the code you need manually". IL-weaving at build-time might be an option, but that's a much more advanced topic.
I have an AttachmentService.cs class that is currently used to upload images to a database and/or a cloud storage container. When uploading to the cloud I have some retry logic in place that I would like to reuse when being called by two separate methods. I would like to pass in each function as a parameter and then call them from within the method they have been passed into. Here are the two signatures I have currently:
C#
//Example: I want to be able to pass the first function and also the second
//I'm sure it can done with generics but can't seem to get it currently
private AttachmentUploadResult UploadAttachmentToGLS(Func<string, Guid, byte?[], string, AttachmentUploadResult> uploadFunction)
private AttachmentUploadResult UploadAttachmentToGLS(Func<AttachmentEntity, AttachmentUploadResult> uploadFunction)
I would like the above code to only have one signature that could take either
Func<string, Guid, byte?[], string, AttachmentUploadResult> uploadFunction or Func<AttachmentEntity, AttachmentUploadResult> uploadFunction so that my method could look like something like this:
private AttachmentUploadResult UploadAttachmentToGLS(Func<parameters, AttachmentUploadResult>uploadFunction)
{
//Some retry logic
uploadFunction(parameters);
//Some more retry logic
}
Is there a way in which I can acheive the above? I have read into Func and do not believe this is the correct delegate to use.
The signature of your function can be just Func<AttachmentUploadResult> - you don't really care about the parameters in the UploadAttachment method, so you should close over them. The call might then look something like this:
Upload(() => SomeUploadMethod(theActual, parameters, toTheMethod));
It also allows you to hide the details of the implementation from the UploadAttachment method - all you care about is "this is the function to call when I want to do the upload".
In C# it's conventional to write in a fairly objective manner, like so:
MyObj obj = new MyObj();
MyReturn ret = obj.DoSomething();
AnotherReturn rett = ret.DoSomethingElse();
I could just write the above like this:
AnotherReturn rett = new MyObj().DoSomething().DoSomethingElse();
However, how does the stackframe work when you have a bunch of function calls in a sequence like this? The example is fairly straightforward but imagine if I've got 50+ function calls chained (this can possibly happen in the likes of JavaScript (/w jQuery)).
My assumption was that, for each function call, a return address is made (to the "dot"?) and the return value (a new object with other methods) is then immediately pumped into the next function call at that return address. How does this work w.r.t. getting to the overall return value (in this example the return address will assign the final function value to rett)? If I kept chaining calls would I eventually overflow? In that case, is it considered wiser to take the objective route (at the cost of "needless" memory assignment?).
It's exactly the same as if you called each method on a separate line, assigning the return value to a variable each time and then using that variable to call the next method.
So your two samples are the same, effectively.
Do you have Reflector? You could try the two methods and inspect the generated IL code to see exactly what differences there are.
Although the 2 calls are same but if you have lot of "Dots" then somewhere it is a code smell (Law of Demeter).
See below discussion
I have been trying to get past this problem for a couple of days now to no avail. I am trying to test the functionality of AnObject.AnAction (preemptive apologies, I have to obfuscate class/method names.) My goal is to keep MyTestObj.do_work(AnObject) from actually doing anything when it is called. It has code that I do want to be called in a unit test environment.
Here is my Unit test code:
Mock< MyTestObj > myTestObj_mock = new Mock< MyTestObj > ();
myTestObj_mock.Setup( e => e.do_work( It.IsAny< AnObject > () ) );
...
AnObject tester = new AnObject();
tester.anAction( myTestObj_mock.Object );
within the method AnObject.AnAction( MyTestObj mto ):
...
mto.do_work( this );
...
It is at this point when ran that I get this error:
System.InvalidCastException : Unable to cast object of type
'myNamespace.AnObject' to type 'System.Delegate'.
MyTestObj.do_work is a virtual method.
I have absolutely no idea why this error is coming up. I've stepped through the code as NUnit ran it and I am certain that is the point in which it crashes. It will not go any further into the code.
I'm really stumped. Does anybody have any idea what is going on?
Thanks in advance!
***Updates***
I tried to create an instance of AnObject within AnObject.AnAction and pass it instead of 'this':
...
AnObject test = new AnObject();
mto.do_work( test );
...
This did not have any effect.
As your question is written you do not need to setup the myTestObj_mock.do_work().
Setup is used to say, when method X is called return value Y. Or alternativly that when method X is called, exception Z is returned. Ask yourself is that really what I need to do?
Here you aren't returning anything from the method:
mto.do_work( this );
Also, here:
myTestObj_mock.Setup( e => e.do_work( It.IsAny< AnObject > () ) );
You aren't defining any Return for your setup.
You should be able to supply a mock myTestObj_mock without defining the setup in this case. Just remove the line with the Setup and run the test again.
A guess:
If you defined the Setup because you wanted your test to make sure AnObject.AnAction really calls the do_work method, what you need to do is define a Verify method rather than a Setup, likewise:
mock.Verify(foo => foo.Execute("ping"));
or in your case something like
myTestObj_mock.Verify(m => m.do_work(It.IsAny< AnObject > ()), Times.AtLeastOnce());
Another guess:
If you defined the mock because you pass a "this" reference and expect do_work to modify some parameters of "this" for the test to pass then you shouldn't be mocking here. Remember that mocks aren't really instances of your objects, so the code that modify the this reference will never get called.
I was finally able to get to a compiler and play with the code and here is what I found. It is basically what Giles said above for his first part of the question.
Here is the code hint for Setup:
Specifies a setup on the mocked type for a call to a value returning method.
And, here is the actual code for Setup
public ISetup<T> Setup(Expression<Action<T>> expression)
So, Setup is actually setting up the code as an Action (a delegate, basically). When the test runner is run, it hits this point and usually expects to feed the delegate to the Returns method
public IReturnsResult<TMock> Returns(TResult value)
So, this is never done, and instead of Mock running through the whole expected path and negotiating all of the code out, then it returns mistyped values.
Sooo, this is basically where Giles explanation is correct. If you are testing that the do_work method is being called, then you want to use Verify (which truly uses your fake object as a mock). However, if not, then you have no need to even set this up as it does nothing. If that is the case, then maybe that piece of code should not be in that specific code block, but you would be best to evaluate that.
And, finally, the Setup method should only be used if you are truly using your object as a stub, simply using it to inject logic into your code.
Hopefully, that makes sense and helps you with your problem.
Also, a Callback might be of use here depending on what you are doing. But, I am not sure. They have many examples in the Moq quickstart
UPDATE FOR MY ATTEMPT AT RECREATING using Version 4.0.10827...and had no issues
[Test]
public void teststuff()
{
Mock<MyTestObj> myTestObj_mock = new Mock<MyTestObj>();
myTestObj_mock.Setup(e => e.do_work(It.IsAny<AnObject>()));
AnObject tester = new AnObject();
tester.anAction(myTestObj_mock.Object);
}
...
public class MyTestObj
{
public virtual void do_work(AnObject o)
{
}
}
public class AnObject
{
public void anAction(MyTestObj obj)
{
obj.do_work(new AnObject());
}
}
I have the below structure in a test of mine, intended to test that a certain log is being called with the right complex argument object, even when it throws an exception which is then wrapped and generally manipulated further.
The logThing has a method:
void AddEntry(LogEntry);
So I am using When..Do to make it throw an exception,
public void UnitTest()
{
// Arrange
ILogThing logThing = Substitute.For<ILogThing>()
SystemUnderTest system = new SystemUnderTest(logThing);
List<LogEntry> actualEntries = new List<LogEntry>();
LogEntry expectedEntry = GetSomeTestData();
logThing.When(
lt => lt.AddEntry(Arg.Do<LogEntry>(r => actualEntries.Add(r)))).Do(
call => { throw new InvalidOperationException("testMessage"); });
// Act
try
{
system.DoSomethingWhichLogs(someArgs)
}
catch(WrappedException ex)
{
// Assert
Assert.AreEqual(1, actualEntries.Count);
Assert.AreEqual(actualEntries[0], expectedEntry);
}
}
However, the expected call to Arg.Do() never happens with this setup.
I have put a breakpoint in the catch block, and used Visual Studio's immediate window to call RecievedCalls<>() on the logThing, and it does have a record of a single call to logThing with the right arguments - it's just that Arg.Do appears to only execute after the When..Do block has finished. Clearly that means that since I am throwing in the When..Do, it never reaches it.
I really didn't expect NSubstitute to order the calls in this way, is that expected behaviour?
If so, is there anything I can do to test the incoming argument like this, or should I just put my argument checking into the main When..Do block (which makes it harder to read)?
The system under test does various things to the exception which include wrapping it together with the logEntry, so it -is- useful for me to have all of these checks in one test - I did think about splitting it into two separate tests, but realized that if I did that, I couldn't easily pin down where the incorrect wrapped output was coming from (it could either be the part that originally generates the logEntry, or the part wrapping it) wheras with this pattern I can check to make sure the logThing is receiving what I expect it to. Still, if there's a better way to do that, I'm certainly open to suggestions.
The exact order of When..Do and Arg.Do isn't defined, and I wouldn't recommend counting on it as I imagine it could change between versions depending on implementation. (If you have a good reason to define it in a particular order please post your suggestion to the usergroup.)
If you just want to check logThing received the expected LogEntry, you can check the argument after the fact using Arg.Is():
logThing.Received().AddEntry(Arg.Is(expectedEntry));
If you need more complex comparison logic, you can do the same thing but use a method to check the argument:
logThing.Received().AddEntry(Arg.Is<LogEntry>(x => CheckLogEntry(x)));
CheckLogEntry can do whatever checks you require, and you can keep the When..Do throwing as before.
If you need to use the When..Do approach, you can can keep your existing approach but move the capture of the argument into the Do call to ensure the order of calls that you expect:
logThing.When(
lt => lt.AddEntry(Arg.Any<LogEntry>())).Do(
call =>
{
actualEntries.Add(call.Arg<LogEntry>());
throw new InvalidOperationException("testMessage");
});
In terms of suggestions for other ways of testing this, I'm not entirely clear on what you are trying to do here, but if you are having trouble isolating where the wrapped output is coming from maybe you could move this responsibility to another dependency? This would let you substitute for this dependency and control exactly where this happened from the perspective of this test.