Paul
Paul

Reputation: 41

Mocking a class with delegates using Moq

The code I have write looks like this:

public class DelegatesClass
{
    IntPtr lib = IntPtr.Zero;

    public delegate Boolean _SetMode(Int32 nMode);
    public _SetMode SetMode;

    public DelegatesClass()
    {
        IntPtr funcPtr;

        lib = NativeMethods.LoadLibrary(fullDllName);

        funcPtr = NativeMethods.GetProcAddress(lib, "SetMode");
        SetMode = (_SetMode)Marshal.GetDelegateForFunctionPointer(funcPtr, typeof(_SetMode;));
    }
}

public class DelegatesUser
{
    public DelegatesUser()
    {
        //...
    }

    public SetUserMode(int mode)
    {
        DelegatesClass ds = new DelegatesClass();
        ds.SetMode(mode);

        //...
    }

}

I have to use a win32 dll in my project, so I created 'DelegateClass'. This does nothing else then making the dll functions available using delegates. My real code is written in a separate class 'DelegateUser'. This way I should be able to mock DelegateClass, and make my code testable.

My test code looks like this:

        var dc= new Mock<DelegatesClass>();

        dc.Setup(x => x.SetMode(It.IsAny<Int32>())
            .Returns(true);

        DelegatesUser du = new DelegatesUser();
        du.SetUserMode(1);

When running the test I get a 'System.ArgumentException' saying: 'Expression is not a method invocation'.

I suppose the problem is that I am trying to fake a delegate, not a real function. How can I make my test code work?

Upvotes: 0

Views: 336

Answers (1)

Alexei Levenkov
Alexei Levenkov

Reputation: 100620

You can't mock field.

Since SetDelegate is just public field you can assign it directly:

var dc = new DelegatesClass();
dc.SetMode = nMode => true;

Notes:

  • consider using interfaces as it would be easier to read/understand as more traditional approach
  • you need to inject dependency on DelegatesClass into DelegatesUser as explicit new DelegatesClass() will not allow you to pass mocked instance.

Sample for injection:

public class DelegatesUser
{
    DelegatesClass ds;
    public DelegatesUser(DelegatesClass ds)
    {
        this.ds = ds;
        //...
    }

    public SetUserMode(int mode)
    {
        // use "ds" passed in constructor instead of new DelegatesClass();
        ds.SetMode(mode);

        //...
    }

}

Upvotes: 2

Related Questions