views:

27

answers:

0

Hi all,

I've made an attempt to unit test a methods in the database layer of my app. In my test I was planning to write mocks to avoid having a live connection to MySQL. I'll write down a simplified version of my code to illustrate. Let's start with the unit test:

[TestMethod()]
public void TestMethod1()
{

DataBaseInterface database = new DataBaseInterface(); // this is the class which has the method I want to unit test

DataSet ds = new DataSet();

ds.Tables.Add(new DataTable("signals"));

ds.Tables[0].Columns.Add(new DataColumn("ID"));
ds.Tables[0].Columns.Add(new DataColumn("Content"));

DataRow row = ds.Tables[0].NewRow();

row["ID"] = "1";
row["Content"] = "Foo";

ds.Tables[0].Rows.Add(row);

MockDataBaseConnection db = new MockDataBaseConnection();


string result = database.GetContent(1);  // this is the method I want to unit test

}

The method I want to unit test looks something like this:

public class DatabaseInterface
{

private MySqlConnectionAdapter _sqlConn;

public string GetContent(int i)
{

MySqlCommand command = _sqlConn.CreateCommand();

command.CommandText = String.Format("");

_sqlConn.Open();

MySqlDataReader reader = command.ExecuteReader();

/// more code here


}

To prevent using an actual database connection in my unitest I wrote a few mockups and here lies the problem. The mockups looks like this:

 public class MySqlConnectionAdapter
    {
        public MySqlConnection _sqlConn; 

        public MySqlConnectionAdapter()
        {
        }

        public MySqlConnectionAdapter(string con)
        {
            _sqlConn = new MySqlConnection(con);
        }

        public event MySqlInfoMessageEventHandler InfoMessage
        {
            add
            {
                _sqlConn.InfoMessage += value;
            }
            remove
            {
                _sqlConn.InfoMessage -= value;
            }
        }

        public virtual event StateChangeEventHandler StateChange
        {
            add
            {
                _sqlConn.StateChange += value;
            }
            remove
            {
                _sqlConn.StateChange -= value;
            }
        }

        public virtual void Open()
        {
            _sqlConn.Open();
        }

        public void Close()
        {
            _sqlConn.Close();
        }

        public string ServerVersion
        {
            get
            {
                return _sqlConn.ServerVersion;
            }
        }

        protected DbTransaction BeginDbTransaction(IsolationLevel isolationLevel)
        {
            return _sqlConn.BeginTransaction(isolationLevel);
        }

        public void ChangeDatabase(string databaseName)
        {
            _sqlConn.ChangeDatabase(databaseName);
        }


        public string ConnectionString
        {
            get
            {
                return _sqlConn.ConnectionString;
            }
            set
            {
                _sqlConn.ConnectionString = value;
            }
        }

        public virtual MySqlCommand CreateCommand()
        {
            return _sqlConn.CreateCommand();
        }

        public string DataSource
        {
            get
            {
                return _sqlConn.DataSource;
            }
        }

        public string Database
        {
            get 
            {
                return _sqlConn.Database;
            }
        }

        public ConnectionState State
        {
            get 
            {
                return _sqlConn.State;
            }
        }
    }

 public class MockDataBaseConnection : MySqlConnectionAdapter
    {
        public DataSet ds;

        public new MockMySqlCommand CreateCommand()
        {
            return new MockMySqlCommand(ds);
        }
    }

    public class MockMySqlCommand
    {
        private DataSet _ds;

        public MockMySqlReader ExcecuteReader()
        {
            return new MockMySqlReader(_ds);
        }

        public MockMySqlCommand(DataSet ds)
        {
            _ds = ds;
        }
    }

    public class MockMySqlReader
    {
        public DataSet _ds;

        private int currRow = 0;

        public MockMySqlReader(DataSet ds)
        {
            _ds = ds;
        }

        public bool Read()
        {
            if (currRow < _ds.Tables[0].Rows.Count)
            {
                currRow++;
                return true;
            }
            else return false;
        }

        public object GetValue(int i)
        {
            return _ds.Tables[0].Rows[currRow][i];
        }
    }

When the line _sqlConn.CreateCommand() is executed it throws and exeption. Why is that? The _sqlConn fiels in my unit test method is a MockDataBaseConnection object and I want it to return a MockMySqlCommand object.

The sealed classed of the MySQL dll is giving me a headache. Can anyone explain how I can fix my code or show a simple example of how to unit test a method which queries a database without actually querying the database.