1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.perfectjpattern.core.behavioral.observer;
22
23 import java.util.*;
24
25 import junit.framework.*;
26
27 import org.perfectjpattern.core.api.behavioral.observer.*;
28 import org.perfectjpattern.core.api.behavioral.observer.data.*;
29 import org.perfectjpattern.core.behavioral.observer.data.*;
30 import org.slf4j.*;
31
32
33
34
35
36
37
38 public final
39 class TestSubject
40 extends TestCase
41 {
42
43
44
45 @SuppressWarnings("unchecked")
46 public void
47 testFaultyObserverDetached()
48 {
49
50 IObserver<NullEventData> myObserver =
51 new IObserver<NullEventData>()
52 {
53
54 public void
55 update(NullEventData anEventData)
56 {
57 throw new RuntimeException("Sorry! I am faulty!");
58 }
59 };
60
61
62 ISubject<NullEventData> mySubject = new Subject<NullEventData>();
63 mySubject.attach(myObserver);
64
65 try
66 {
67 mySubject.notifyObservers(NullEventData.getInstance());
68 }
69
70 catch (RuntimeException anException)
71
72 {
73 fail("Subject is not protected from faulty Observer instances");
74 }
75
76 assertEquals("Subject did not automatically detach faulty Observers",
77 0, mySubject.size());
78 }
79
80
81
82
83
84
85 public void
86 testStatusObserver()
87 {
88 theLogger.debug("Running assertions ... ");
89
90 assertEquals(
91 "First observer incorrectly received completion notifications.",
92 1, theFirstObserver.getSuccessCount());
93 assertEquals(
94 "First observer incorrectly received failure notifications.",
95 1, theFirstObserver.getFailureCount());
96
97 assertEquals(
98 "Second observer incorrectly missed completion notifications.",
99 2, theSecondObserver.getSuccessCount());
100 assertEquals(
101 "Second observer incorrectly missed failure notifications.", 2,
102 theSecondObserver.getFailureCount());
103
104 assertEquals(
105 "Third observer incorrectly missed completion notifications.",
106 2, theThirdObserver.getSuccessCount());
107 assertEquals(
108 "Third observer incorrectly missed failure notifications.", 2,
109 theThirdObserver.getFailureCount());
110
111 theLogger.debug("Completed test");
112 }
113
114
115
116
117
118
119 public void
120 testProgressObserver()
121 {
122 theLogger.debug("Running assertions ... ");
123
124 List<ProgressData> myExpectedProgress = Arrays
125 .asList(new ProgressData[] {
126 ProgressData.STARTED,
127 new ProgressData(Status.IN_PROGRESS,
128 "Testing in progress ...", 20),
129 new ProgressData(Status.IN_PROGRESS,
130 "Testing in progress ...", 40),
131 new ProgressData(Status.IN_PROGRESS,
132 "Testing in progress ...", 60),
133 new ProgressData(Status.IN_PROGRESS,
134 "Testing in progress ...", 80),
135 ProgressData.COMPLETED });
136
137 int i = 0;
138 for (ProgressData myProgress : theFourthObserver.getProgress())
139 {
140 assertEquals("Invalid progress notification sequence.",
141 myExpectedProgress.get(i++), myProgress);
142 }
143
144 theLogger.debug("Completed test");
145 }
146
147
148 @SuppressWarnings("unchecked")
149 public void
150 testClear()
151 {
152 theLogger.debug("Running assertions ... ");
153
154 ISubject<NullEventData> mySubject = new Subject<NullEventData>();
155
156
157 mySubject.attach(new IObserver<NullEventData>()
158 {
159
160 public void
161 update(NullEventData anEventData)
162 {
163
164 }
165 });
166
167 assertEquals("Size method implemented incorrectly.", 1,
168 mySubject.size());
169
170
171 mySubject.clear();
172
173 assertEquals("Clear method implemented incorrectly.", 0,
174 mySubject.size());
175
176 theLogger.debug("Completed test");
177 }
178
179
180
181
182
183
184 public void
185 testSize()
186 {
187 theLogger.debug("Running assertions ... ");
188
189 assertEquals("Status Subject contains invalid amount of observers", 2,
190 theStatusSubject.size());
191 assertEquals("Progress Subject contains invalid amount of observers",
192 1, theProgressSubject.size());
193
194 theLogger.debug("Completed test");
195 }
196
197
198
199
200
201 @SuppressWarnings("unchecked")
202 public void
203 testSimple()
204 {
205 theLogger.debug("Started simple Observer usage test");
206
207 theLogger.debug("Step #1 := Define Event data type");
208 class MyEventData implements IEventData
209 {
210
211 public
212 MyEventData(final String aValue)
213 {
214 theValue = aValue;
215 }
216
217
218 public final String
219 getValue()
220 {
221 return theValue;
222 }
223
224
225 private final String theValue;
226 }
227
228 theLogger.debug("Step #2 := Define Observer instance");
229 IObserver<MyEventData> myObserver = new IObserver<MyEventData>()
230 {
231
232 public void
233 update(MyEventData anEventData)
234 {
235 theLogger.debug("update call received with data: " +
236 anEventData.getValue());
237 }
238 };
239
240 theLogger.debug("Step #3 := Create ISubject instance");
241 ISubject<MyEventData> mySubject = new Subject<MyEventData>();
242
243 theLogger.debug("Step #4 := Attach Observer to Subject");
244 mySubject.attach(myObserver);
245
246 theLogger.debug("Step #5 := Notify observers");
247 mySubject.notifyObservers(new MyEventData("Hello Observer!"));
248
249 theLogger.debug("Completed test");
250 }
251
252
253
254
255 @Override
256 protected void
257 setUp()
258 throws Exception
259 {
260 super.setUp();
261
262 theLogger.debug("Creating Observer pattern test fixture ... ");
263
264
265 fixture();
266
267 theLogger.debug("Completed Observer pattern test fixture.");
268 }
269
270
271
272
273
274
275
276 @SuppressWarnings("unchecked")
277 private void
278 fixture()
279 {
280
281
282
283 theLogger.debug("Step #1 := Create ISubject instance.");
284 theStatusSubject = new Subject<StatusData>();
285
286 theLogger.debug("Step #2 := Create IObserver instances.");
287 theFirstObserver = new TestStatusObserver();
288 theSecondObserver = new TestStatusObserver();
289 theThirdObserver = new TestStatusObserver();
290
291 theLogger.debug("Step #3 := Attach IObserver to ISubject.");
292 theStatusSubject.attach(theFirstObserver, theSecondObserver,
293 theThirdObserver);
294
295 theLogger.debug("Step #4 := Send notifications.");
296 theStatusSubject.notifyObservers(StatusData.FAILED);
297 theStatusSubject.notifyObservers(StatusData.COMPLETED);
298
299 theLogger.debug("Eventually detach observers.");
300 theStatusSubject.detach(theFirstObserver);
301
302 theLogger.debug("Send more notifications.");
303 theStatusSubject.notifyObservers(StatusData.FAILED);
304 theStatusSubject.notifyObservers(StatusData.COMPLETED);
305
306
307
308
309 theLogger.debug("Step #1 := Create ISubject instance.");
310 theProgressSubject = new Subject<ProgressData>();
311
312 theLogger.debug("Step #2 := Create IObserver instances.");
313 theFourthObserver = new TestProgressObserver();
314
315 theLogger.debug("Step #3 := Attach IObserver to ISubject.");
316 theProgressSubject.attach(theFourthObserver);
317
318 theLogger.debug("Step #4 := Send notifications.");
319 theProgressSubject.notifyObservers(ProgressData.STARTED);
320 for (int myI = 1; myI < 5; myI++)
321 {
322 theProgressSubject.notifyObservers(new ProgressData(
323 Status.IN_PROGRESS, "Testing in progress ...", 5, myI));
324 }
325 theProgressSubject.notifyObservers(ProgressData.COMPLETED);
326 }
327
328
329
330
331
332
333
334 private static final
335 class TestStatusObserver
336 implements IObserver<StatusData>
337 {
338
339 public final int
340 getSuccessCount()
341 {
342 return theSuccessCount;
343 }
344
345
346 public final int
347 getFailureCount()
348 {
349 return theFailureCount;
350 }
351
352
353 public void
354 update(StatusData aStatusData)
355 {
356 if (Status.COMPLETED == aStatusData.getStatus())
357 {
358 theSuccessCount++;
359 }
360 else
361 if (Status.FAILED == aStatusData.getStatus())
362 {
363 theFailureCount++;
364 }
365 }
366
367
368
369
370 private int theFailureCount = 0;
371 private int theSuccessCount = 0;
372 }
373
374
375
376
377
378
379 private static final
380 class TestProgressObserver
381 implements IObserver<ProgressData>
382 {
383
384 public void
385 update(ProgressData aProgressData)
386 {
387 theProgress.add(aProgressData);
388 }
389
390
391 public final
392 Collection<ProgressData>
393 getProgress()
394 {
395 return theProgress;
396 }
397
398
399
400
401 private Collection<ProgressData> theProgress =
402 new ArrayList<ProgressData>();
403 }
404
405
406
407
408 private ISubject<StatusData> theStatusSubject = null;
409 private ISubject<ProgressData> theProgressSubject = null;
410 private TestStatusObserver theFirstObserver = null;
411 private TestStatusObserver theSecondObserver = null;
412 private TestStatusObserver theThirdObserver = null;
413 private TestProgressObserver theFourthObserver = null;
414
415
416
417
418 private final Logger theLogger = LoggerFactory.getLogger(this.getClass());
419 }