jsedding commented on a change in pull request #5:
URL: 
https://github.com/apache/sling-org-apache-sling-junit-core/pull/5#discussion_r529609030



##########
File path: 
src/main/java/org/apache/sling/junit/annotations/SlingAnnotationsTestRunner.java
##########
@@ -56,4 +57,16 @@ protected Object createTest() throws Exception {
             return top.process(super.createTest());
         }
     }
+
+    @Override
+    public void run(RunNotifier notifier){
+        try {
+            super.run(notifier);
+        } catch (Exception e) {
+            log.error("Test 'run' method", e);
+        } finally {
+            AnnotationsProcessor ap = (AnnotationsProcessor) top;
+            ap.closeAllServices();

Review comment:
       I think this is not what you want to do here. If I understand the code 
correctly, `AnnotationsProcessor` implements `TestObjectProcessor` and is a 
service, which in turn implies it is a singleton. On the other hand, there is 
probably an instance of `SlingAnnotationsTestRunner` per test class. The 
current code, if I read it correctly, closes all services of all tests. This 
may not be a practical issue as long as tests are not executed concurrently, 
but it is still not correct.
   
   The `ServiceGetter` instances are created for a specific test, namely the 
one created by the call `top.process(super.createTest());` above. I would add a 
method to `TestObjectProcessor` that allows cleaning up after a test. I'll 
provisionally call it `TestObjectProcessor#cleanupTest(Object test)`. Then 
instead of keeping an instance of `TestObjectProcessor` in a field, I would 
keep an instance of the `Object` returned by `super.createTest()` in a field. 
In the finally block, this object can then be passed to the cleanup method.
   
   In `AnnotationsProcessor` you keep an `IdentityHashMap<Object, 
List<ServiceGetter>>`, which you initialize in the `#process(Object)` method. 
Finally, in the `#cleanup(Object)` method, you close all `ServiceGetter`s 
pertaining to the `object` and remove it from the map. Don't forget to clear 
the map on `@Deactivate` of `AnnotationsProcessor`.
   
   You may want to provide a no-op default implementation of `#cleanup(Object)` 
in the interface `TestObjectProcessor`. This might (I'm not sure it does) 
reduce the required version increase, and it would certainly keep any 
implementations out in the wild running without code changes (if they indeed 
exist... who knows).
   
   ALTERNATIVE: If you're feeling adventurous and have some time, there would 
be an alternative to adding a new method to the API. You could use 
`WeakReference` and `ReferenceQueue` with a cleanup thread inside 
`AnnotationsProcessor` in order to close the `ServiceGetter`s. The approach is 
[nicely summed up on stack 
overflow](https://stackoverflow.com/questions/14450538/using-javas-referencequeue/14450693#14450693),
 where `Foo` would be the test `Object` and `Bar` the `List<ServiceGetter>`.

##########
File path: src/main/java/org/apache/sling/junit/impl/AnnotationsProcessor.java
##########
@@ -35,9 +34,11 @@
 public class AnnotationsProcessor implements TestObjectProcessor {
     private Logger log = LoggerFactory.getLogger(getClass());
     private BundleContext bundleContext;
-    
+    private ArrayList<ServiceGetter<? extends Object>> serviceGetters;

Review comment:
       I prefer using interface types for all fields rather than 
implementations. That makes refactoring to a different type easier and the diff 
less noisy.

##########
File path: 
src/main/java/org/apache/sling/junit/annotations/SlingAnnotationsTestRunner.java
##########
@@ -56,4 +57,16 @@ protected Object createTest() throws Exception {
             return top.process(super.createTest());
         }
     }
+
+    @Override
+    public void run(RunNotifier notifier){
+        try {
+            super.run(notifier);
+        } catch (Exception e) {
+            log.error("Test 'run' method", e);

Review comment:
       Don't catch the exception here. You are decorating, so ideally the 
calling code gets the same result as without the decoration (except for desired 
changes/side-effects). In case my previous comments prompted you to add the 
catch block, I'm sorry for causing confusion. The finally block is sufficient, 
because it gets called in any case, exception or not.




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


Reply via email to