MethodConfig

Abstract

A MethodConfig is a configuration for proxied methods. They control the behavior of a proxied method. There is one configuration for each method. Templated methods don't have configurations - but each instantiation (c++) is given a unique configuration.

var

Closer inspection of the MethodConfig classes will show that there are a very large number of child classes and encapsulating classes. I do this to hide and expose certain properties of method configurations that aren't relevant to all types of functions. For example, a function that returns void doesn't need a configuration Return. When writing test code with BeanProxy, it is highly recommended to declare MethodConfig's as var.

The following example shows this best practice. Both code segments do the exact same thing.

Do this:
var methodConfig = ProxyManager.GetFunc<int, double, string, char, Dictionary<long, byte[]>>(proxy.Foo);
And not this:
FuncConfig<int, double, string, char, Dictionary<long, byte[]>> methodConfig = ProxyManager.GetFunc<int, double, string, char, Dictionary<long, byte[]>>(proxy.Foo);

Useful Functions

IsReal

By default, calling a proxy method without having declared it as real or not real will throw a NotImplementedException. The reason I chose this design was to help the tester be more aware, and be in explicit control, of what functions were being called. Setting IsReal to true causes the proxy class to invoke the class's actual function. Setting IsReal to false causes the proxy class to not call the actual function.

Return

'Return' is a set only property. It is also strong type based on the return type of the method. If the method is a void return, there will not be a Return property. When using a method of an unknown signature (as can be done with ProxyManager.GetMethodConfig), see Callback.

Setting the Return value automatically sets IsReal to false. Also, a simple function is created for you that returns the given value. This dynamic function is set to the Callback.
public abstract class Class
{
  public abstract int Foo();
}
public class TestClass
{
  public void Test()
  {
    var proxy = ProxyManager.CreateProxy<Class>();
    ProxyManager.GetFunc<int>(proxy.Foo).Return = 14;

    Assert.AreEqual(14, proxy.Foo());
  }
}

Callback

The Callback is a delegate which is invoked when the configuration's IsReal is false. The delegate signature of the Callback will match the method being redirected. Using Callback in a lambda can greatly simplify the locality of a test. see the examples in Advanced.

I may refer to the Callback method as either the fake method or the proxy method throughout this documentation.
public abstract class Class
{
  public abstract int Foo(int i, int j);

  public string Bar()
  {
    return Foo(4, 2).ToString();
  }
}
public class TestClass
{
  public void Test()
  {
    var proxy = ProxyManager.CreateProxy<Class>();
    ProxyManager.GetFunc<int, int, int>(proxy.Foo).Callback =
    (i, j) =>
    {
      return i * j;
    };

    ProxyManager.GetFunc<string>(proxy.Bar).IsReal = true;

    Assert.AreEqual("8", proxy.Bar());
  }
}

Param1, Param2, Param3, Param4, and Param5

When a proxy method is invoked references to the parameters passed are saved for later testing. These Param properties can therefore be used to confirm what values were passed to the method.
public class Class
{
  public virtual void Foo()
  {
    Bar(10);
  }

  public virtual Bar(int i)
  {
    throw new NotImplementedException();
  }
}

public class ClassTest
{
  public void Test()
  {
    var proxy = ProxyManager.CreateProxy<Class>();

    ProxyManager.GetAction(proxy.Foo).IsReal = true;
    var barConfig = ProxyManager.GetAction<int>(proxy.Bar);
    barConfig.IsReal = false;

    proxy.Foo();

    Assert.AreEqual(10, barConfig.Param1, "first parameter passed to Bar");
  }
}

Count

Keeps track of the number of times a method is invoked. The count is incread for both real and fake occurances.
public class Class
{
  public int NumReals { get; set; }

  public virtual void Foo()
  {
    NumReals++;
  }
}

public class ClassTest
{
  public void Test()
  {
    var proxy = ProxyManager.CreateProxy<Class>();

    var fooConfig = ProxyManager.GetAction(proxy.Foo);

    fooConfig.IsReal = true;
    proxy.Foo();

    fooConfig.IsReal = false;
    proxy.Foo();

    Assert.AreEqual(2, fooConfig.Count, "Number of calls to Foo");
    Assert.AreEqual(1, proxy.NumReals, "Number of real calls to Foo");
  }
}

Behavior

The basic use of Callback is to define a single proxy method. Each subsequent call will repeatedly call the same proxy method. This type of behavior is defined as CallbackBehavior.Repeat. Repeat is the default behavior, there are also RunOnce and RepeatLast. Callback can define more than just one proxy method and actually represents a list of callbacks. Each behavior will execute one callback at a time.

The following example demostrates that a Callback can point to a list of methods, and that invoking the callback will loop through those methods, one at a time.
public abstract class Class
{
  public abstract int Foo();
}
public class TestClass
{
  public void Test()
  {
    var proxy = ProxyManager.CreateProxy<Class>();
    var config = ProxyManager.GetFunc<int>(proxy.Foo);

    Assert.AreEqual(MethodBehavior.Repeat, config.Behavior);

    config.Callback += () => 1;
    config.Callback += () => 2;

    Assert.AreEqual(1, proxy.Foo());
    Assert.AreEqual(2, proxy.Foo());

    Assert.AreEqual(1, proxy.Foo());
    Assert.AreEqual(2, proxy.Foo());
  }
}

RepeatLast iterates the callback list 0 through n - 1, just like Repeat, except that when reaching the n -1th callback, it continue to call that same method. RunOnce iterates from 0 to n - 1 just once. Subsequent invocations to the method will throw an InvalidOperationException.

SetOutParameter

The use of out and ref has admittedly little support, but support there is. See Advanced use of Ref and Out for further discussion of these issues. This method allows setting the out value for a proxy method.

ParameterHistory

The Param properties give access to only the last parameters passed to a proxy method; the ParameterHistory keeps a record of all parameters passed in the order they were given in the order the proxy method was invoked.

Last edited May 6, 2010 at 7:21 AM by payonel, version 13

Comments

No comments yet.