如何为测试目的模拟网络故障(在 C# 中)?

Posted

技术标签:

【中文标题】如何为测试目的模拟网络故障(在 C# 中)?【英文标题】:How to simulate network failure for test purposes (in C#)? 【发布时间】:2010-10-03 06:05:03 【问题描述】:

我正在为新应用构建可称为 DAL 的东西。不幸的是,与数据库的网络连接是一个真正的问题。

我希望能够在我的测试范围内临时阻止网络访问,以便我可以确保我的 DAL 在这些情况下按预期运行。

更新:有许多手动方法可以禁用网络,但如果我可以在测试本身中启用/禁用它肯定会很好。

【问题讨论】:

可能想在网络工具上查看这个问题以模拟慢速连接:***.com/questions/1094760/… 【参考方案1】:

目前,我只是通过设置一个虚假的静态 IP 来“禁用”网络,如下所示:

using System.Management;

class NetworkController


    public static void Disable()
    
        SetIP("192.168.0.4", "255.255.255.0");
    

    public static void Enable()
    
        SetDHCP();
    


    private static void SetIP(string ip_address, string subnet_mask)
    
        ManagementClass objMC = new ManagementClass("Win32_NetworkAdapterConfiguration");
        ManagementObjectCollection objMOC = objMC.GetInstances();

        foreach (ManagementObject objMO in objMOC) 
            if ((bool)objMO("IPEnabled")) 
                try 
                    ManagementBaseObject setIP = default(ManagementBaseObject);
                    ManagementBaseObject newIP = objMO.GetMethodParameters("EnableStatic");

                    newIP("IPAddress") = new string[]  ip_address ;
                    newIP("SubnetMask") = new string[]  subnet_mask ;

                    setIP = objMO.InvokeMethod("EnableStatic", newIP, null);
                
                catch (Exception generatedExceptionName) 
                    throw;
                
            


        
    

    private static void SetDHCP()
    
        ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
        ManagementObjectCollection moc = mc.GetInstances();

        foreach (ManagementObject mo in moc) 
            // Make sure this is a IP enabled device. Not something like memory card or VM Ware
            if ((bool)mo("IPEnabled")) 
                ManagementBaseObject newDNS = mo.GetMethodParameters("SetDNSServerSearchOrder");
                newDNS("DNSServerSearchOrder") = null;
                ManagementBaseObject enableDHCP = mo.InvokeMethod("EnableDHCP", null, null);
                ManagementBaseObject setDNS = mo.InvokeMethod("SetDNSServerSearchOrder", newDNS, null);
            
        
    

【讨论】:

【参考方案2】:

为您正在使用的网络类连接类(例如 WebClient)编写一个包装器,并带有一个开关:)

要么这样,要么在防火墙中阻止您的应用程序。

【讨论】:

这是一个非常有趣的命题。你知道有什么方法可以非侵入性地处理这个吗? (即不修改代码?)任何这样的 Win32 网络 API 包装器?【参考方案3】:

如果您尝试为您的应用程序完全中断网络,拔下网络电缆将起作用。有时您可能有一个具有多个数据源(在不同机器上)的数据访问层,在这种情况下,您可以使用 Rhino Mocks 之类的 Mock 框架在测试中模拟异常。这是您可能在测试中使用的一些伪代码

void TestUserDBFailure()

    // ***** THIS IS PSEUDO-CODE *******
    //setting up the stage - retrieval of the user info create an exception
    Expect.Call(_userRepository.GetUser(null))
       .IgnoreArguments()
       .Return(new Exception());

    // Call that uses the getuser function, see how it reacts
    User selectedUser = _dataLoader.GetUserData("testuser", "password");        

【讨论】:

【参考方案4】:

尝试在会话中途阻止与防火墙的连接?

我也喜欢包装器的想法,但这有点抽象问题,您可能无法获得准确的真实世界行为。此外,插入包装层然后将其移除可能比它的价值更麻烦。

编辑:运行脚本以随机或按设定的时间间隔打开/关闭网络适配器?

【讨论】:

【参考方案5】:

可能对模拟“真实”网络问题没有帮助,但您可以在测试范围内将数据库连接字符串指向不存在的机器。

【讨论】:

我同意简单的启用/禁用不会让您在处理“真正的”网络问题方面走得太远,但它是测试连接中断时应用程序会发生什么的起点。 【参考方案6】:

试试 Toxiproxi,它可以模拟网络中断。

他们有 REST API 甚至 .NET Client API 以编程方式更改网络模拟(来自您的测试代码) https://github.com/shopify/toxiproxy

【讨论】:

【参考方案7】:

寻找一个允许您限制带宽(并完全切断带宽)的 WAN 模拟器。当我的应用程序在带宽受限的环境中运行时,我发现用户体验的变化总是很有趣。查看here 了解一些信息。

【讨论】:

【参考方案8】:

如blog entry 中所述,您可以使用一个工具来模拟数据库应用程序测试中的高延迟和低带宽。

【讨论】:

【参考方案9】:

取决于您希望模拟的特定网络问题。对于大多数人来说,它就像“服务器无法访问”一样简单,在这种情况下,您只需尝试连接到不存在的服务器即可。但是要小心,因为您想要一些可路由但不应答的东西。尝试连接到 dkjdsjk.com 将立即失败(DNS 查找),但尝试连接到 www.google.com:1433 将(可能)由于防火墙而超时 - 这是您的应用程序在您的数据库服务器运行时的行为方式下来。

【讨论】:

【参考方案10】:

刚刚找到一个可以直接关闭 TCP 连接的替代方案:

http://lamahashim.blogspot.ch/2010/03/disabling-network-using-c.html

它基于 Windows IP Helper API(使用 DllImport): http://msdn.microsoft.com/en-us/library/windows/desktop/aa366073(v=vs.85).aspx

【讨论】:

【参考方案11】:

使用模拟对象创建可配置的、可破坏的真实版本——在本例中为数据库。

【讨论】:

以上是关于如何为测试目的模拟网络故障(在 C# 中)?的主要内容,如果未能解决你的问题,请参考以下文章

具体网络故障解析——升级带宽

如何为网络摄像头提供论据

如何为winform C#应用程序实现密码恢复[关闭]

如何为每个测试模拟不同的 useLocation 值?

如何为 elasticsearch 模拟繁重的磁盘 / io 负载

如何为 Android Studio 创建小米模拟器?或者任何其他方式在小米模拟器上测试应用程序?