patterncsharpMinor
Integration tests for a repository with the help of AutoFixture
Viewed 0 times
thewithautofixturetestshelprepositoryforintegration
Problem
I find it hard to do integration tests for a repository and very time consuming.
Things I think about when creating integration tests for a repository:
Should I skip them?
Should I create an in memory database?
Should I create a local database for the test?
Should I delete inserted data?
Is my repository caching results, should I use another instance to verify results?
I implemented this repository with Dapper as it will be the only repository in my solution and Dapper is so light weight. I am a big fan of NHibernate but I felt it was an overkill.
I would be happy for any comments on how my tests could be better :)
Here are my tests
```
[TestFixture]
public class NotificationRepositoryTests
{
private IFixture fixture;
private TestNotificationRepository notificationRepository;
[SetUp]
public void SetUp()
{
fixture = new Fixture();
fixture.Customize(c => c.With(x => x.Processed, CreateSqlServerFriendlyDate()));
notificationRepository = new TestNotificationRepository();
}
[TearDown]
public void TearDown()
{
notificationRepository.DeleteInserted();
}
[Test]
public void InsertShouldReturnCreateAnId()
{
var notification = fixture.Build().Without(x => x.Id).Create();
notificationRepository.Insert(notification);
Assert.That(notification.Id, Is.Not.EqualTo(0));
}
[Test]
public void InsertShouldInsertNotification()
{
var notification = fixture.Create();
notificationRepository.Insert(notification);
var result = notificationRepository.Get(notification.Id);
notification.AsSource().OfLikeness().ShouldEqual(result);
}
[Test]
public void UpdateShouldUpdateNotification()
{
//Arrange
var notification = fixture.Create();
notificationRepository.Insert(notification);
var notificationUpdate = fixture.Build().With(x => x.Processed, CreateSqlServerFriendlyDate()).Create();
Things I think about when creating integration tests for a repository:
Should I skip them?
Should I create an in memory database?
Should I create a local database for the test?
Should I delete inserted data?
Is my repository caching results, should I use another instance to verify results?
I implemented this repository with Dapper as it will be the only repository in my solution and Dapper is so light weight. I am a big fan of NHibernate but I felt it was an overkill.
I would be happy for any comments on how my tests could be better :)
Here are my tests
```
[TestFixture]
public class NotificationRepositoryTests
{
private IFixture fixture;
private TestNotificationRepository notificationRepository;
[SetUp]
public void SetUp()
{
fixture = new Fixture();
fixture.Customize(c => c.With(x => x.Processed, CreateSqlServerFriendlyDate()));
notificationRepository = new TestNotificationRepository();
}
[TearDown]
public void TearDown()
{
notificationRepository.DeleteInserted();
}
[Test]
public void InsertShouldReturnCreateAnId()
{
var notification = fixture.Build().Without(x => x.Id).Create();
notificationRepository.Insert(notification);
Assert.That(notification.Id, Is.Not.EqualTo(0));
}
[Test]
public void InsertShouldInsertNotification()
{
var notification = fixture.Create();
notificationRepository.Insert(notification);
var result = notificationRepository.Get(notification.Id);
notification.AsSource().OfLikeness().ShouldEqual(result);
}
[Test]
public void UpdateShouldUpdateNotification()
{
//Arrange
var notification = fixture.Create();
notificationRepository.Insert(notification);
var notificationUpdate = fixture.Build().With(x => x.Processed, CreateSqlServerFriendlyDate()).Create();
Solution
Overall
On the whole I like your approach and your tests look pretty robust. I have tended to have simple 'does this execute' type integration tests at a repository level that are manually validated, since they only really need to be run if you're updating the repository or the underlying database. I then rely on higher level use case integration tests, where the repositories are used under the hood, to flag up any data discrepancies. Your approach of having the tests cleanup after themselves is a nice tidy approach.
Consider Categories
It looks like you're using NUnit and if you are, then the one thing I would suggest you do though is mark your different types of tests using categories. I leave most unit tests without categories, however I mark integration tests with categories so that they can easily be excluded / included into builds. You can use the attribute at either a 'Test' or a 'TestFixture' level.
If you're running tests from within Visual Studio, then Categories are interpreted as 'Traits', so again you can easily exclude them from the tests that you're running, or just run the specific category/trait. NUnit itself and the console runner support multiple category attributes (so you can mark all tests 'IntegrationTests' and mark db tests 'DBIntegrationTests' then run subsets), however not all test runners recognise multiple categories (the default VS runner seems to just pick the first one).
On the whole I like your approach and your tests look pretty robust. I have tended to have simple 'does this execute' type integration tests at a repository level that are manually validated, since they only really need to be run if you're updating the repository or the underlying database. I then rely on higher level use case integration tests, where the repositories are used under the hood, to flag up any data discrepancies. Your approach of having the tests cleanup after themselves is a nice tidy approach.
Consider Categories
It looks like you're using NUnit and if you are, then the one thing I would suggest you do though is mark your different types of tests using categories. I leave most unit tests without categories, however I mark integration tests with categories so that they can easily be excluded / included into builds. You can use the attribute at either a 'Test' or a 'TestFixture' level.
[Category("DBIntegrationTest")]If you're running tests from within Visual Studio, then Categories are interpreted as 'Traits', so again you can easily exclude them from the tests that you're running, or just run the specific category/trait. NUnit itself and the console runner support multiple category attributes (so you can mark all tests 'IntegrationTests' and mark db tests 'DBIntegrationTests' then run subsets), however not all test runners recognise multiple categories (the default VS runner seems to just pick the first one).
Code Snippets
[Category("DBIntegrationTest")]Context
StackExchange Code Review Q#110618, answer score: 3
Revisions (0)
No revisions yet.