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.