2009 Advent Calendar December 8th
So far we've kind of assumed for most of the time that the ImportantObject is easy to create. If not you probably want to create an interface for the ImportantObject. And creating an interface is probably a good idea anyway. So this is a refactoring of all code we have from yesterday.
1: public interface ImportantInterface
2: {
3: void ImportantMethod();
4: }
5:
6: public class ImportantObject : ImportantInterface
7: {
8: public void ImportantMethod()
9: {
10: // Do things.
11: }
12: }
13:
14: public interface Lock
15: {
16: void Lock();
17: void Unlock();
18: }
19:
20: public class MutexLock : Lock
21: {
22: private readonly Mutex _lock = new Mutex();
23:
24: public void Lock()
25: {
26: _lock.WaitOne();
27: }
28:
29: public void Unlock()
30: {
31: _lock.ReleaseMutex();
32: }
33: }
34:
35: public class Transaction : IDisposable
36: {
37: private readonly Lock _lock;
38: public ImportantInterface ImportantObject { get; private set; }
39:
40: public Transaction(ImportantInterface importantObject, Lock aLock)
41: {
42: ImportantObject = importantObject;
43: _lock = aLock;
44: _lock.Lock();
45: }
46:
47: public void Dispose()
48: {
49: _lock.Unlock();
50: }
51: }
52:
53: class FakeLock : Lock
54: {
55: public bool IsLocked { get; private set; }
56:
57: public FakeLock()
58: {
59: IsLocked = false;
60: }
61:
62: public void Lock()
63: {
64: IsLocked = true;
65: }
66:
67: public void Unlock()
68: {
69: IsLocked = false;
70: }
71: }
72:
73: class DummyObject : ImportantInterface
74: {
75: public void ImportantMethod()
76: {
77: Assert.True(false, "Dummy should never be used");
78: }
79: }
80:
81: public class When_using_a_transaction
82: {
83: private FakeLock _lock;
84:
85: public When_using_a_transaction()
86: {
87: _lock = new FakeLock();
88: }
89:
90: [Fact]
91: void It_should_take_lock_when_created()
92: {
93: Assert.False(_lock.IsLocked);
94: using (Transaction transaction = new Transaction(new ImportantObject(), _lock))
95: {
96: Assert.True(_lock.IsLocked);
97: }
98: }
99:
100: [Fact]
101: void It_should_release_lock_when_leaving_scope()
102: {
103: using (Transaction transaction = new Transaction(new ImportantObject(), _lock))
104: {
105: Assert.True(_lock.IsLocked);
106: }
107: Assert.False(_lock.IsLocked);
108: }
109: }
110:
111: public class Given_a_transaction
112: {
113: private Transaction _transaction = new Transaction(new DummyObject(), new FakeLock());
114:
115: [Fact]
116: void It_should_return_an_ImportantObject()
117: {
118: Assert.NotNull(_transaction.ImportantObject);
119: }
120: }