/* * Grapht, an open source dependency injector. * Copyright 2014-2015 various contributors (see CONTRIBUTORS.txt) * Copyright 2010-2014 Regents of the University of Minnesota * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package org.grouplens.grapht.util; import org.grouplens.grapht.InjectionException; import org.grouplens.grapht.Injector; import org.grouplens.grapht.InjectorBuilder; import org.junit.Ignore; import org.junit.Test; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.inject.Inject; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; /* * Grapht, an open source dependency injector. * Copyright 2014-2015 various contributors (see CONTRIBUTORS.txt) * Copyright 2010-2014 Regents of the University of Minnesota * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ public class ComponentLifecycleTest { @Test public void testClosesAutoCloseable() throws Exception { InjectorBuilder bld = InjectorBuilder.create(); Flag closed = new Flag(); bld.bind(Flag.class).to(closed); Injector injector = bld.build(); try { CloseableComponent comp = injector.getInstance(CloseableComponent.class); assertThat(comp, notNullValue()); } finally { injector.close(); } // Check that close was called. assertTrue("close was called", closed.isSet()); } /** * If we inject an instance of an AutoCloseable, it should not be closed. */ @Test public void testDoesNotCloseAutoCloseableInstance() throws Exception { InjectorBuilder bld = InjectorBuilder.create(); Flag closed = new Flag(); bld.bind(Flag.class).to(closed); bld.bind(CloseableComponent.class).to(new CloseableComponent(closed)); Injector injector = bld.build(); try { CloseableComponent comp = injector.getInstance(CloseableComponent.class); assertThat(comp, notNullValue()); } finally { injector.close(); } // Check that close was not called. assertFalse("close was called", closed.isSet()); } /** * Test that the lifecycle management calls pre-destroy methods. */ @Test public void testCallsPreDestroy() throws Exception { InjectorBuilder bld = InjectorBuilder.create(); Flag closed = new Flag(); bld.bind(Flag.class).to(closed); Injector injector = bld.build(); try { LifecycleShutdownComponent comp = injector.getInstance(LifecycleShutdownComponent.class); assertThat(comp, notNullValue()); } finally { injector.close(); } // Check that close was called. assertTrue("close was called", closed.isSet()); } /** * Test that the lifecycle management does not call pre-destroy methods on an instance. */ @Test public void testDoesNotCallPreDestroyOnInstance() throws Exception { InjectorBuilder bld = InjectorBuilder.create(); Flag closed = new Flag(); bld.bind(LifecycleShutdownComponent.class).to(new LifecycleShutdownComponent(closed)); Injector injector = bld.build(); try { LifecycleShutdownComponent comp = injector.getInstance(LifecycleShutdownComponent.class); assertThat(comp, notNullValue()); } finally { injector.close(); } // Check that close was called. assertFalse("close was called", closed.isSet()); } /** * Test that the lifecycle management calls post-construct methods */ @Test public void testCallsPostConstruct() throws Exception { InjectorBuilder bld = InjectorBuilder.create(); Flag setup = new Flag(); bld.bind(Flag.class).to(setup); Injector injector = bld.build(); try { PostConstructComponent comp = injector.getInstance(PostConstructComponent.class); assertThat(comp, notNullValue()); assertTrue("setup was called", setup.isSet()); } finally { injector.close(); } // Check that close was called. assertTrue("close was called", setup.isSet()); } /** * Flag component for detecting closure. */ public static class Flag { private boolean value = false; public void set() { value = true; } public boolean isSet() { return value; } } /** * Component implementing AutoCloseable that should be closed. */ public static class CloseableComponent implements AutoCloseable { private final Flag flag; @Inject public CloseableComponent(Flag f) { flag = f; } @Override public void close() throws Exception { flag.set(); } } /** * Component with PreDestroy method that must be called. */ public static class LifecycleShutdownComponent { private final Flag flag; @Inject public LifecycleShutdownComponent(Flag f) { flag = f; } @PreDestroy public void shutdown() { flag.set(); } } /** * component with post-construct methods */ public static class PostConstructComponent { private Flag setup; // we use setter injection to make sure PostConstruct is called after setters @Inject public void setFlag(Flag f) { setup = f; } @PostConstruct public void setup() { assertThat(setup, notNullValue()); setup.set(); } } }