简体   繁体   English

有没有人在.NET中成功模拟过Socket类?

[英]Has anyone successfully mocked the Socket class in .NET?

I'm trying to mock out the System.net.Sockets.Socket class in C# - I tried using NUnit mocks but it can't mock concrete classes. 我试图在C#中模拟出System.net.Sockets.Socket类 - 我尝试使用NUnit模拟但它不能模拟具体的类。 I also tried using Rhino Mocks but it seemed to use a real version of the class because it threw a SocketException when Send(byte[]) was called. 我也尝试过使用Rhino Mocks,但它似乎使用了该类的真实版本,因为它在调用Send(byte [])时抛出了SocketException。 Has anyone successfully created and used a Socket mock using any mocking framework? 有没有人使用任何模拟框架成功创建和使用Socket模拟?

Whenever I run into these kinds of problems with Moq I end up creating an interface to abstract away the thing I can't mock. 每当我遇到Moq的这些问题时,我最终都会创建一个接口来抽象出我无法模拟的东西。

So in your instance you might have an ISocket interface that implements the Send method. 因此,在您的实例中,您可能有一个实现Send方法的ISocket接口。 Then have your mocking framework mock that instead. 然后让你的模拟框架模拟而不是。

In your actual code, you'd have a class like this 在您的实际代码中,您将拥有这样的类

public class MySocket : ISocket
{
  System.Net.Sockets.Socket _socket;

  public void MySocket(System.Net.Sockets.Socket theSocket)
  {
    _socket = theSocket;
  }

  public virtual void Send(byte[] stuffToSend)
  {
    _socket.Send(stuffToSend);
  }

}

Not sure if that meets your needs, but it's an option. 不确定这是否符合您的需求,但这是一个选择。

The reason you get a SocketException when you call the Send method is because Send is not an overridable method. 调用Send方法时出现SocketException的原因是Send不是可覆盖的方法。 For RhinoMocks to be able to mock the behavior of a property or method, it has to either be defined in an interface (which we then create our mock off) or is overridable. 为了使RhinoMocks能够模拟属性或方法的行为,它必须在接口中定义(然后我们创建模拟关闭)或者可以覆盖。

Your only solution to this is to create a mockable wrapper class (as suggested by thinkzig). 您唯一的解决方案是创建一个可模拟的包装类(如thinkzig所示)。

The above class only Mocks your Send Method. 上面的类只模拟你的发送方法。 This actually mocks a Socket. 这实际上嘲笑了一个Socket。 It Inherits all of Socket and then Implements the ISocket interface. 它继承了所有Socket,然后实现了ISocket接口。 ISocket needs to implement the signatures of any Socket methods or properties you need to mock ISocket需要实现您需要模拟的任何Socket方法或属性的签名

//internal because only used for test code
internal class SocketWrapper : Socket, ISocket
{
    /// <summary>
    /// Web Socket
    /// </summary>
    public SocketWrapper():base(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
    {
    }

    //use all features of base Socket
}

The interface looks like this with two methods declined: 界面看起来像这样两种方法被拒绝:

public interface ISocket
{
    void Connect(IPAddress address, int port);
    int Send(byte[] buffer, int offset, int size, SocketFlags socketFlags, out SocketError errorCode);
}

The Class that uses them has 2 constructors. 使用它们的类有2个构造函数。 One injects an ISocket for testing and then one that makes it's own Socket that the application uses. 一个注入一个ISocket用于测试,然后一个使它成为应用程序使用的自己的Socket。

public class HTTPRequestFactory3
{
internal ISocket _socket;


    /// <summary>
    /// Creates a socket and sends/receives information.  Used for mocking to inject ISocket
    /// </summary>
    internal HTTPRequestFactory3(ISocket TheSocket)
    {
     _socket = TheSocket as ISocket;
     this.Setup();
    }

    /// <summary>
    /// Self Injects a new Socket.
    /// </summary>
    public  HTTPRequestFactory3()
    {
        SocketWrapper theSocket = new SocketWrapper();
        _socket = theSocket as ISocket;
        this.Setup();
    }
}

Then your tests can create a ISocket, set up expectations and verify them running all the same code the above class will use with a real socket. 然后你的测试可以创建一个ISocket,设置期望并验证它们运行上述类将与真正的套接字一起使用的所有相同代码。 This test validates that section code. 此测试验证该部分代码。

   [Test]
   public void NewSocketFactoryCreatesSocketDefaultConstructor()
        {
            webRequestFactory = new HTTPRequestFactory3();
            Assert.NotNull(webRequestFactory._socket);
            Socket testSocket = webRequestFactory._socket as Socket;
            Assert.IsInstanceOf<Socket>(testSocket);
        }

I've created an example console application using the method thinkzig suggests (an adapter class for Socket). 我使用thinkzig建议的方法(Socket的适配器类)创建了一个示例控制台应用程序。 It uses RhinoMocks and NUnit. 它使用RhinoMocks和NUnit。 You can download it here: How to mock System.Net.Sockets.Socket . 你可以在这里下载它: 如何模拟System.Net.Sockets.Socket

You'd better to create an interface and mock it in your test, and implement a wrapper class in your code, that forward all method calls to .NET socket as thinkzig said. 您最好在测试中创建一个接口并对其进行模拟,并在代码中实现一个包装类,将所有方法调用转发给.NET套接字,如thinkzig所述。 Look at this link, it's same issue: How do you mock out the file system in C# for unit testing? 看看这个链接,同样的问题: 你如何模拟C#中的文件系统进行单元测试?

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

相关问题 有没有人成功使用过WMI Win32_PatchPackage类? (C#) - Has anyone successfully used the WMI Win32_PatchPackage class? (C#) 是否还有其他人对 Azure Batch 成功完成 .NET 中试用订阅的示例任务有疑问? - Does anyone else have issues with Azure Batch successfully completing sample tasks on a trial subscription in .NET? 更改模拟的getResponse .net - Change mocked getResponse .net AWS .NET无法判断对象是否已成功删除 - AWS .NET no way to tell if an object has been successfully deleted 有没有人将ADOMD.NET与WPF DataGrid一起使用? - Has anyone used ADOMD.NET with WPF DataGrid? 有没有人使用嵌入在.NET桌面应用程序中的Open Office? - Has anyone used Open Office embedded in a .NET Desktop Application? 有没有人得到枚举解析器类的副本(“停止疯狂”) - Has anyone got a copy of the Enumeration Parser class (“Stop the Madness”) 是否有人在C#AWS Lambda函数或AWS Linux EC2实例中成功运行SQL Server连接器? - Has anyone successfully run a SQL Server connector within a C# AWS Lambda function, or AWS Linux EC2 instance? 无法初始化模拟类的成员 - Cannot initialize member of mocked class 验证方法是否在模拟类中调用 - Verify if method called in the mocked class
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM