chevron-thin-right chevron-thin-left brand cancel-circle search youtube-icon google-plus-icon linkedin-icon facebook-icon twitter-icon toolbox download check linkedin phone twitter-old google-plus facebook profile-male chat calendar profile-male
Welcome to Typemock Community! Here you can ask and receive answers from other community members. If you liked or disliked an answer or thread: react with an up- or downvote.
0 votes
Today it is a bit cumbersome to check mocked method parameters.

One possibility is the following where the expected value is passed to the delegate via Check.CustomCheck:

public static bool CheckParameter(ParameterCheckerEventArgs data)
{
    return data.ArgumentValue == data.ExpectedValue;
}

[Test]
public void CheckParametersWithCustomCheck()
{
    MockManager.Init();
    Mock mock = MockManager.Mock(typeof(TestedClass));
    TestedClass t = new TestedClass();
    // setup expectation, test first argument by calling our CheckParameter
    // with ExpectedValue set
    string expectedParameter = "String";
    mock.ExpectCall("SomeMethod").Args(
       Check.CustomChecker(
          new ParameterCheckerEx(CheckParameter), expectedParameter));
    t.SomeMethod("String");
    MockManager.Verify();
}

Another possibility is by using anonymous methods like this:

[Test]
public void CheckParametersWithAnonymousMethod()
{
    MockManager.Init();
    Mock mock = MockManager.Mock(typeof(TestedClass));
    TestedClass t = new TestedClass();
    // setup expectation, test first argument by calling our CheckParameter
    // with ExpectedValue set
    string expectedParameter = "String";
    mock.ExpectCall("SomeMethod").Args(
        new ParameterCheckerEx(delegate(ParameterCheckerEventArgs args)
        {
            if ((string)args.ArgumentValue == expectedParameter)
                return true;
            else
                return false;
        }));
    t.SomeMethod("String");
    MockManager.Verify();
}


I still think it could be simpler and more intuitive. The developer always have to instantiate the ParameterCheckerEx and possibly the wrap it in a Check.ParameterChecker.
Why not overload the void IParameters.Args(params object[] args) method, so it accepts a delegate?

public void Args(params object[] args) { }

public void Args(ParameterCheckerEx args) { }

public void Args(ParameterCheckerEx args, object expectedValue) { }


So it can be used like this:

[Test]
public void CheckParametersArgsOverloading1()
{
    MockManager.Init();
    Mock mock = MockManager.Mock(typeof(TestedClass));
    TestedClass t = new TestedClass();
    // setup expectation, test first argument by calling our CheckParameter
    // with ExpectedValue set
    string expectedParameter = "String";
    mock.ExpectCall("SomeMethod").Args(
        delegate(ParameterCheckerEventArgs args)
        {
            if ((string)args.ArgumentValue == expectedParameter)
                return true;
            else
                return false;
        });        
    t.SomeMethod("String");
    MockManager.Verify();
}
[Test]
public void CheckParametersArgsOverloading2()
{
    MockManager.Init();
    Mock mock = MockManager.Mock(typeof(TestedClass));
    TestedClass t = new TestedClass();
    // setup expectation, test first argument by calling our CheckParameter
    // with ExpectedValue set
    string expectedParameter = "String";
    mock.ExpectCall("SomeMethod").Args(
        delegate(ParameterCheckerEventArgs args)
        {
            if (args.ArgumentValue == args.ExpectedValue)
                return true;
            else
                return false;
        }, expectedParameter);
    t.SomeMethod("String");
    MockManager.Verify();
}


It hides the complexity and delivers a much clearer interface for parameter checking.
asked by Lybecker (680 points)

5 Answers

0 votes
You are correct that the API can be cumbersome.
Your API's look cleaner. :D
The only problem is that using the API we can check only the first parameter.

We will need to create a different API, off my head either
public void Args(params  ParameterCheckerEx[] args)

To handle more then one parameter.
I am not sure that this will compile. But even if it does, ALL parameters must be checked with a delegate.

or have one delegate check ALL parameter:

Args(AllParameterChecker checkerDelegate);


Then we can
mock.ExpectCall("SomeMethod").Args(
delegate(AllParameterCheckerEventArgs args)
{
   if ((args[0].ArgumentValue == expectedParameter0) &&
       (args[1].ArgumentValue == expectedParameter1))
      return ParameterCheck.Validated;
   else
      return ParameterCheck.Failed("Wrong Arguments");
});

But this will be harder to see where the error is in case of faliure.

Of course in .NET 3.0 it will be nicer:
mock.ExpectCall("SomeMethod").Args( args => 
{
   if ((args[0].ArgumentValue == expectedParameter0) &&
       (args[1].ArgumentValue == expectedParameter1))
      return ParameterCheck.Validated;
   else
      return ParameterCheck.Failed("Wrong Arguments");
});


What do you think?
answered by scott (32k points)
0 votes
I am not sure that the AllParameterChecker will work in practices. You’ll never know how many parameters is enough?

Just out of curiosity – how do I check and therefore parse more than one parameter to the Args method?
answered by Lybecker (680 points)
0 votes
Here is how you can check many arguments:
mock.ExpectCall("SomeMethod").Args("arg1","arg2");

with Checks
mock.ExpectCall("SomeMethod").Args(Check.IsEqual("arg1"),Check.IsEqual("arg2"));

with Custom Checks
mock.ExpectCall("SomeMethod").Args(
   Check.CustomChecker(delegate(ParameterCheckerEventArgs  args)
       {  return args.ArgumentValue == args.ExpectedValue; } , "arg1"),
   Check.CustomChecker(delegate(ParameterCheckerEventArgs  args)
       {  return args.ArgumentValue == args.ExpectedValue; } , "arg2")
);


Having an AllParameterChecker will allow to test both parameters in one go.
You will be able to ask: allArgs.Length to find the number of parameters.
and reach each parameter via: allArgs[i].

mock.ExpectCall("SomeMethod").Args(
   delegate(AllParameterCheckerEventArgs  args)
   {  
      if (args.Length == 2) 
      {
         return args[0].ArgumentValue == "args1" &&
             args[1].ArgumentValue == "args2";
      }
      return false;
   }
);
answered by scott (32k points)
0 votes
Of cause that makes sense. I should have been able to figure out the multiple parameters stuff. I just haven’t tried it like that. I use a delegate with an anonymous method to get access to the outer method scope variables.

It also starts making sense with the AllParameterChecker. Although I don’t see any reason to differentiate between ParameterChecker and AllParameterChecker except if it has some build-in intelligence e.g. checking the number of parameters. I might be required not to break the existing implementations – you know more about that, than me.
answered by Lybecker (680 points)
0 votes
Hi,
We have added this feature request. Thanks for the feedback 8)
answered by scott (32k points)
...