2009 Advent Calendar December 1st
One way of adding tests for thread safety is to let the important object handle the locking through two protected members:
1: public class ImportantObject
2: {
3: private Mutex _lock = new Mutex();
4:
5: public void ImportantMethod()
6: {
7: Lock();
8: // Do things.
9: Unlock();
10: }
11:
12: protected virtual void Lock()
13: {
14: _lock.WaitOne();
15: }
16:
17: protected virtual void Unlock()
18: {
19: _lock.ReleaseMutex();
20: }
21: }
Now we can write a specification that looks like this:
1: public class Given_an_ImportantObject
2: {
3: class TestableImportantObject : ImportantObject
4: {
5: public int NumberOfLocks { get; private set; }
6:
7: public TestableImportantObject()
8: {
9: NumberOfLocks = 0;
10: }
11:
12: protected override void Lock()
13: {
14: ++NumberOfLocks;
15: }
16:
17: protected override void Unlock()
18: {
19:
20: }
21: }
22:
23: private TestableImportantObject _importantObject = new TestableImportantObject();
24:
25: [Fact]
26: void It_should_take_lock_when_ImportantMethod_is_called()
27: {
28: _importantObject.ImportantMethod();
29: Assert.Equal(1, _importantObject.NumberOfLocks);
30: }
31: }
Now we have a test/specification for thread safety! or do we?