2009 Advent Calendar December 18th
Yet another passing test to make sure our MutexLock works as expected:
1: public class Given_a_locked_MutexLock : IDisposable
2: {
3: private MutexLock _lock = new MutexLock();
4: private Thread _thread;
5: private bool _gotLock = false;
6:
7: public Given_a_locked_MutexLock()
8: {
9: _thread = new Thread(() =>
10: {
11: _lock.Lock();
12: _gotLock = true;
13: _lock.Unlock();
14: });
15: }
16:
17: public void Dispose()
18: {
19: if (_thread != null)
20: {
21: _thread.Abort();
22: }
23: }
24:
25: private void TakeLockAndStartThread()
26: {
27: _lock.Lock();
28: _thread.Start();
29: }
30:
31: [Fact(Timeout = 1000)]
32: void It_should_not_take_the_lock()
33: {
34: TakeLockAndStartThread();
35: Assert.False(_thread.Join(250));
36: Assert.False(_gotLock);
37: }
38:
39: [Fact(Timeout = 1000)]
40: void It_should_take_lock_when_released()
41: {
42: TakeLockAndStartThread();
43: Assert.False(_thread.Join(250));
44: _lock.Unlock();
45: Assert.True(_thread.Join(500));
46: Assert.True(_gotLock);
47: }
48: }
Note that I moved taking the lock from the constructor to a common helper method. This has to do with how xUnit.net runner creates objects and runs tests together with a timeout. Turns out that the object is created in one thread and then the test method is run in a separate thread if a timeout is used. In theory, if everything works as expected I don't really need the timeout but it is very nice to have it just in case the code doesn't work as expected.