简体   繁体   English

使用Moq与代表模拟课程

[英]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'. 我必须在项目中使用Win32 dll,因此创建了'DelegateClass'。 This does nothing else then making the dll functions available using delegates. 然后,使用委托将dll函数变为可用,则此操作无济于事。 My real code is written in a separate class 'DelegateUser'. 我的真实代码写在单独的类'DelegateUser'中。 This way I should be able to mock DelegateClass, and make my code testable. 这样,我应该能够模拟DelegateClass,并使我的代码可测试。

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'. 运行测试时,我得到一个'System.ArgumentException'字样:'Expression不是方法调用'。

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? 如何使测试代码正常工作?

You can't mock field. 您不能模拟字段。

Since SetDelegate is just public field you can assign it directly: 由于SetDelegate只是公共字段,因此您可以直接分配它:

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. 您需要将对DelegatesClass依赖项注入DelegatesUser因为显式的new DelegatesClass()将不允许您传递模拟实例。

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);

        //...
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM