C# Stress Test - Simulate multiple access to a giv

2019-04-08 07:44发布

问题:

How can you simulate/stress test about 100 users accessing a given shared resource (e.g. Database) in a c# unit test?

回答1:

Assuming you're accessing real DB you're in the scope of integration tests. The simplest way is to access the resource from multiple threads. For example:

[Test]
public void SimpleStressTest()
{
    bool wasExceptionThrown = false;
    var threads = new Thread[100];
    for(int i = 0; i < 100; i++)
    {
        threads[i] = 
            new Thread(new ThreadStart((Action)(() =>
            {
                try
                {                        
                    AccessDB();
                }
                catch(Exception)
                {
                    wasExceptionThrown = true;
                }

            })));
    }

    for(int i = 0; i < 100; i++)
    {
        threads[i].Start();
    }    
    for(int i = 0; i < 100; i++)
    {
        threads[i].Join();
    }

    Assert.That(wasExceptionThrown, Is.False);
}

This test is not deterministic since you can't control the threads flow. If you want to make sure, for example, that 100 connections can be opened at the same time, you can place a hook in the logic of AccessDB() which will force it to wait before it closes the connection to the DB.

For example, instead of the previous thread action:

try
{                        
    AccessDB(sychObject);
}
catch(Exception)
{
    wasExceptionThrown = true;
}

After starting all the threads make sure you have 100 threads waiting on the sychObject and only then release it and join the threads. The same can be achieved by making the logic of CloseConnection() (for example) virtual and write the test against an inheriting class the waits in CloseConnection(). For example:

public class DataBase
{
    public void AccessDB()
    {
        // Do logic here before closing connection
        CloseConnection();
    }

    protected virtual void CloseConnection()
    {
        // Real Logic to close connection
    }
}

public class FakeDataBase : DataBase
{
    ManualResetEvent sychObject;

    public FakeDataBase(ManualResetEvent sychObject)
    {
        this.sychObject = sychObject;
    }

    override protected void CloseConnection()
    {
        sychObject.WaitOne();
        base.CloseConnection();
    }
}


回答2:

You simply cannot do useful load testing of anything via a unit test. Load testing is a separate activity with completely different goals. Your unit tests should prove that the code functions to spec. Load testing is about finding bottlenecks so you can address them.



回答3:

I've done performance and load testing with a free util called WCAT http://www.iis.net/downloads/community/2007/05/wcat-63-(x86). It is a little dated now, but it was easy to get started, there are plenty of online articles about it and it seemed flexible.