Lets check what Fluent NHibernate has to offer:
1) SessionSource class which helps to deal with NHibernate configuration, session management and recreating database schema. Why is it useful? "Just" to check if mappings are correct you don't need to have any test data, you need only clear schema and database to connect with. You can use SQLite to create in-memory database. This is a neat and robust solution and moreover it eliminates external dependency -- we don't need any external database any more. Check the example:
1: [SetUp]
2: public void SetUp()
3: {
4: // create and configure persistance model including changes in Conventions
5: var persistenceModel = new PersistenceModel();
6: persistenceModel.Conventions.GetTableName =
7: type =>
8: String.Format("[{0}.{1}]", type.Namespace.Substring(type.Namespace.LastIndexOf('.') + 1), type.Name);
9: persistenceModel.Conventions.GetPrimaryKeyNameFromType = type => type.Name + "ID";
10: persistenceModel.Conventions.GetForeignKeyNameOfParent = type => type.Name + "ID";
11: persistenceModel.Conventions.GetForeignKeyName = prop => prop.Name + "ID";
12:
13: // add mappings
14: persistenceModel.addMappingsFromAssembly(typeof (Product).Assembly);
15:
16: // configure nhibernate using SQLite database
17: var config = new SQLiteConfiguration()
18: .InMemory()
19: .ShowSql();
20:
21: sessionSource = new SessionSource(config.ToProperties(), persistenceModel);
22:
23: // create NHibernate session
24: session = sessionSource.CreateSession();
25:
26: // recreate schema
27: sessionSource.BuildSchema(session);
28: }
Here is an implementation of BuildSchema(...) method:
1: public void BuildSchema(ISession session)
2: {
3: IDbConnection connection = session.Connection;
4:
5: string[] drops = _configuration.GenerateDropSchemaScript(_dialect);
6: executeScripts(drops, connection);
7:
8: string[] scripts = _configuration.GenerateSchemaCreationScript(_dialect);
9: executeScripts(scripts, connection);
10: }
As you can see, it uses NHibernate methods to generate DDL for dropping and creating tables for selected dialect (SQLite in this case). One thing worth noticing is that DDLs will be as accurate as mappings. So if you skip some information (like nullable fields) then don't expect to see it there!
2) Thanks to the SessionSource class we can query in-memory database and we have access to NHibernate Session ... it's time to check our mappings, we can use PersistenceSpecification class to do that:
1: [Test]
2: public void ProductReviewTest()
3: {
4: new PersistenceSpecification<ProductReview>(session)
5: .CheckProperty(x => x.Comments, "some nice comment")
6: .CheckProperty(x => x.EmailAddress, "test@test.com")
7: .CheckProperty(x => x.ModifiedDate, DateTime.Today)
8: .CheckProperty(x => x.Rating, 4)
9: .CheckProperty(x => x.ReviewDate, DateTime.Today)
10: .CheckProperty(x => x.ReviewDate, DateTime.Today)
11: .CheckProperty(x => x.ReviewerName, "test name")
12: .CheckReference(x => x.Product, CreateNewProduct())
13: .VerifyTheMappings();
14: }
Under the hood PersistenceSpecification class will save the object (ProductReview) to the database and then using another connection it will fetch the object back to make sure that all properties have correct values set. It's not a revolution but for sure it can save lots of time and thanks to neat and readable code it will increase maintainability.
Source Code
As always you can download the source code, and the whole sample web application. You will find there separate project for tests. I have created an AbstractTestBase class which is responsible for configuration and it also exposes NHibernate session. There are also tests for mappings, which use exposed NHibernate session and at least on my machine all tests pass ;)
(EDIT: Examples in this post have been updated on 8.02.2009 to reflect changes in Fluent NHibernate API)
Useful Links:
- Part I - Fluent NHibernate introduction and quick start guide
- Part II - Conventions and AutoPersistenceModel
- Fluent NHibernate and Collections mapping
- Source code
- AdventureWorks database which is used by the sample web application
3 comments:
Can you 6-11 in the first section of code? (i.e. why do you need this convention code?)
Thanks,
S
Basically you want to have one set of mappings which you use in your application and the same set you want to reuse while writing the tests. That's why you need to apply the same conventions.
The code in this example is out-dated. API for conventions has changed significantly, you can learn more about conventions here: http://marekblotny.blogspot.com/2009/04/conventions-after-rewrite.html
Hello Marek,
The Article on Fluent NHibernate - Integration Tests is informative. It gives detailed information about it .Thanks for Sharing the information on Integration tests. Software Testing Services
Post a Comment