Repository Pattern, NHibernate and Unit Testing
I am working on ASP MVC 3 PROJECT with repository pattern, I want to know how exactly we have to write a unit test for CRUD operations on repository(aggregate). I am stuck with Saving part where I want to rollback my save, remove it from database, something like Transaction.rollback, it i not working for me, can anyone please help me with some sample code on how to do this.
Here is the overview of my code
Begintransaction
session.save(Parent parent) in repository
transaction.commit.
Unittest:
opensession;
_rep.Save(parent);
Actually if there is a way or a piece of code that i can put into the TearDown part in my test class that runs after each test Say in mycase after Save method and deletes that particular record, and one more thing con开发者_运维百科sidered to be is, AS THIS RUNS AFTER EACH TEST I DNT know how to handle it when it tries to do the same thing after other test methids (delete, get all) etc.., i am all confused.
First of all, you should decide if it's a classic unit test you want to perform or an integration test with a database involved. If you want to test your entities you should use a fake or a mock repository that you inject into your test class (IOC container would be nice). Hence there is no need for rollback (as no database is involved). If you perform an integration test, then I suggest you use an Sqlite in memory database. It's realy lightweight. One problem though with Sqlite is that it doesn't provide transaction support.
If you want to test your database access you can use an in memory database like SQLite for testing. This database will disappear when your tests are finished and you don't have to clean up the testdata. An other advantage is the speed. In memory DBs are much faster than SQL Server etc.
I suppose that you need the rollback to keep database clean and to avoid interference between tests. You can achieve this by providing own database to each unit test. There is a nice article how to achieve this in effective way on Sql Server compact edition: http://www.differentpla.net/content/2009/03/using-sql-server-compact-edition-unit-testing.
EDIT: Some examples: http://nhdatabasescopes.codeplex.com/.
In your NUnit Setup and TearDown methods, you need to drop and then create the specified tables(using a script) in your database. So before and after each of your tests run, all your data will of-course get deleted leaving only empty tables for you to test.
The following example uses MySql database, but even for other databases, the code should be quite similar:
public class DatabaseCleanup
{
private string _connectionString;
private MySqlConnection _mySqlConnection;
private string _filePath;
public DatabaseCleanup()
{
_filePath = @"C:\createdatabase.sql";
_connectionString = @"Server=localhost;Port=3306;Database=dbname;Uid=username;Password=password;";
_mySqlConnection = new MySqlConnection(_connectionString);
}
public void Create()
{
string script = File.ReadAllText(_filePath);
ExecuteScript(script);
}
private void ExecuteScript(string script)
{
try
{
MySqlCommand command = new MySqlCommand(script, _mySqlConnection);
_mySqlConnection.Open();
command.ExecuteNonQuery();
_mySqlConnection.Close();
}
catch (Exception exception)
{
throw;
}
finally
{
_mySqlConnection.Close();
}
}
}
The script createdatabase.sql
mentioned in the above code is simply an sql file that contains drop table and create table statements, which you can supply as per your database. Following is just a sample:
DROP TABLE IF EXISTS `my_table`;
CREATE TABLE `my_table` (
`Id` varchar(50) NOT NULL,
`Name` varchar(50) NOT NULL,
PRIMARY KEY (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
You can then use the DatabaseCleanup class in your NUnit test class' Setup and TearDown methods:
DatabaseCleanup databaseCleanup = new DatabaseCleanup();
databaseCleanup.Create();
Be careful not to run this database cleanup code on production environments. Run such tests on development and testing environment only.
P.S., I don't like people saying here to use in-memory databases like SqlLite. That completely defeats the whole purpose of Integration Testing. That would mean to test your code using a different database in your development environment, and then go and deploy on a different database platform on the production server; and then face a nightmare!
精彩评论