I am in the process of building a "get to know NHibernate project).
My unit tests (nunit) provide the repository layer the same configuration as the normal mvc site but using "SQLiteConfiguration.Standard.InMemory()" instead of "MsSqlConfiguration.MsSql2008". My hope is that I can use fluent nhibernate and automapping exactly the same way but have a quick in memory db for tests and a real db for the app.
In the repository constructor it creates the Session object for all queries to use and also implements IDisposable which will ensure the session is dealt with correctly. For example a save article method would look like:
public void SaveArticle(Article article)
{
Session.SaveOrUpdate(article);
Session.Flush();
}
So far the MVC site all seems to work correctly, and my tests are passing. I think I have come across an issue that must be a problem with my design.
So far I have two objects:
class Article
{
public virtual int Id {get; set; }
public virtual IList<Tag> Tags {get; set; }
}
class Tag
{
public virtual int Id {get; set; }
public virtual string Text {get; set; }
}
I only want the DB to store ONE instance of each tag. So many articles could use the same tag. So I wrote this test:
[Test]
public void TestDeletingTagWillNotDeleteOthersTagV2()
{
Article article = new Article();
article.Tags.Add(new Tag { Text = "C#" });
article.Tags.Add(new Tag { Text = "VB" });
Service.SaveArticle(article);
Article article2 = new Article();
article2.Tags.Add(new Tag { Text = "C#" });
Service.SaveArticle(article2);
Guid article1Id = article.Id;
Guid article2Id = article2.Id;
article = null;
article2 = null;
Article article3 = Service.GetArticle(article1Id);
Article article4 = Service.GetArticle(article2Id);
Assert.AreEqual(2, article3.Tags.Count);
Assert.AreEqual(1, article4.Tags.Count);
Assert.AreEqual(2, Service.Tags.Count);
article3.Tags.RemoveAt(0);
Service.SaveArticle(article3);
Article article5 = Service.GetArticle(article1Id);
Article article6 = Service.GetArticle(article2Id);
Assert.AreEqual(1, article5.Tags.Count);
Assert.AreEqual(1, article6.Tags.Count);
Assert.AreEqual(2, Service.Tags.Count);
}
This test passes, but I believe it should fail. (it does when you run the MVC site i.e. the first article only has one tag, "VB" not "C#" and "VB".
I believe its because as the session is still open nhibernate is still holding onto everything and remembers what there was.
My main question is how do I test this with the in memory db? How do I ensure that after the saves and removal of a shared tag the articles still have what they should have?
The table structure it has created is, (which I feel is wrong, should have a link table):
Article:
Id (PK, uniqueid, not null)
...........
Tag
Id (PK, uniqueid, not null)
Text (nvarchar, null)
Article_id (FK, uniqueid, null)
Not sure how to use the fluent automapping to setup a link table so that one tag can be shared across multiple Articles and one article can have many tags
Believe I found how to ensure that the Tags and articles have a link table:
configuration.Mappings(m => m.AutoMappings.Add((AutoMap.AssemblyOf<Article>())
.Override<Article>(map => map.IgnoreProperty(x => x.IsPublished))
.Override<Article>(map => map.HasManyToMany(a => a.Tags).Cascade.All())
.Conventions.Add(DefaultCascade.All()))