views:

93

answers:

2

I'm trying to write a bunch of unit tests for my classes, most of which are persisted.

In my test class I have a bunch of member variables that contain the data that I'm pushing into my objects which are then created in the repository.

One of the first tests is to create a record in the repository based on the data in the member variables. I then retrieve the UniqueIdentifier from the datastore and set it to one of the member variables.

In one of the later tests, I want to use the UniqueIndentifier to retrieve the record from the datastore but the value is null, as if the value has not been set!

By the way, I'm using MSTest (the default visual studio one).

If anyone has any suggestions I'd greatly appreciate them.

+2  A: 

Your tests should each be small, independent, and fast. In theory, unit tests can run in any order, individually, or as a package of tests, and they should not rely on any configuration values (such a connection string).

It sounds like you are trying to persist to a physical data store, and then test that the value actually exists in a later test. Now, you've written a test that has a dependency on a previous test. That's too fragile of a set up.

EDIT 1

I don't test my repositories. I use NHibby, and I know it works, as long as my configuration is valid. And if my configuration is wrong, I wouldn't use a unit test to verify this.

I write MVC or WPF/M-V-VM applications. With these styles, it is very easy to write tests against the controller or view model tiers. I will mock out my repositories in a fashion similar to this

[TestMethod]
public void TestThatSomethingHappens()
{
    var repo = new Mock<IRepository>();
    repo.Setup(x => x.Find<Customer>(It.IsAny<int>())).Returns(_somePredefinedCustomer);
    // etc.
}

So, when my code pulls a value from a repository, it will pull out a predefined customer, and that customer was already built in a test setup method (or constructor, if you're using xUnit). If I want to test what happens when no customer is found, that will be a different test, to I'll have a .Returns(null), and see what my controller or WinForm does.

Jarrett Meyer
That makes sense. Would your suggestion therefore be to create a new record in the repository for each retrieval test, and then delete that record at the end of the test?
Jason Summers
@Jason Summers See edits
Jarrett Meyer
+1  A: 

It sounds like you might be doing an integration test. As Jarett menetioned your tests are way to fraigle as they rely on state from a previous test. If you need to setup some sort of state for you tests look at using the TestInitialize attribute and the TestCleanup attribute. These methods will be called on each Test ran. If you need to setup state for the whole test group you can use ClassInitialize and ClassCleanup However that might not be recommended since I do not believe order is guaranteed when MSTests are ran.

Putting it all together

[ClassInitialize]
public void ClassInitialize()
{
//Do something to create the data store, create files, setup DB, etc..
}
[ClassCleanup]
public void ClassCleanup()
{
//Tear down the resources
}

[TestInitialize]
public void TestInitialize()
{
//inject some data for the test from the resource created in ClassInitialize()
}

[TestCleanup]
public void TestCleanup()
{
//Clean up any data or values you injected into your datastore from TestInitialize()
}
Mark