Reputation: 639
Haven't really used much unit testing before, but read up on it a bit and got the idea that you really only should test 1 thing at a time. But how to do this in a nice way when for example saving and retrieving an object? I can't see that the save worked without using the "retrieve" function. And can't test the retrieve without saving something. At the moment I tried something like this... How can I assure that my test can know which one is not working?
[TestMethod]
public void TestSaveObject()
{
TestStorage storage = new TestStorage();
ObejctToSave s1 = new ObejctToSave {Name = "TEST1"};
ObejctToSave s2 = new ObejctToSave { Name = "TEST2" };
storage.SaveObject(s1);
storage.SaveObject(s2);
List<ObjectToSave> objects = storage.GetObjects();
Assert.AreEqual(2, objects.Count);
Assert.AreEqual("TEST1", objects[0].Name);
Assert.AreEqual("TEST2", objects[1].Name);
}
Upvotes: 4
Views: 2349
Reputation: 14755
I like the Idea to test one function by using it-s inverse-function even if this means testing two things at a time and this is probably an integrationtest and not a unittest.
However there are some problems i experienced doing this.
storage.GetObjects()
might retrieve the ojects in the wrong order so your test might fail although every single object was handled correctly. The same applies for objects with sub-lists.ObejctToSave
and forget to update the corresponding test you get a false positive - ObejctToSave
tells you success althoug the new property is not persisted properly.For a workaround for these limitations in dotnet i did this
compare<t>(t object1, t object2, params string[] propertyNamesToBeIgnoredInTest)
that uses reflection to compare the properties and sorts sub-list before comparing them.Upvotes: 1
Reputation: 35891
You noted yourself that unit-tests ought to test one thing at a time. And yet here you're testing two things - storage and retrieval.
If you want to test your service layer for handling persistence correctly, mock the persistence object (repository), and then call service methods to add object - verifying that appropriate methods on repository were called. The same for retrieval.
The main issue is whether:
you are implementing a persistence library. If yes, you should of course test peristence methods, using mock objects that will fake OS calls to file system operations.
you want to test your persistence methods (as your example suggests), but they are using 3rd party library. It doesn't make sense for unit-tests - this is the part when integration testing plays its role.
Briefly speaking - unit test tests a single unit - a "module" of your code separately from other modules. Other parts are being mocked for the purpose of verifying only the code of the unit being tested.
Integration test on the other hand tests a group of modules working together. Often integration tests are implemented to tests typical use cases of your whole system, sometimes they are used for regression testing of only a group of modules for example. There are many possibilities, but the point is that modules are being tested working together - hence integration.
Upvotes: 3
Reputation: 33242
Interesting point. I think to do it in the most proper TDD way ( that wouldn't be necessary the way it should ) is to create a TestStorage mock, and assert the proper calls are satisfied on it. So you can create a separate test for the Save an Retrieve, both with the mock and proper expectations on it.
Upvotes: 0