changeset 710:3a47a18e5b4a

Unit tests for DAO registration Add new unit tests to test that agent, and gui all register DAOs as services on startup. Extends cli tests to test for unregistration of services too. Reviewed-by: neugens, jerboaa Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2012-October/003761.html
author Omair Majid <omajid@redhat.com>
date Mon, 22 Oct 2012 18:24:19 -0400
parents decac7295693
children ced47d3fad73 098a78b25a40
files agent/cli/src/main/java/com/redhat/thermostat/agent/cli/AgentApplication.java agent/cli/src/test/java/com/redhat/thermostat/agent/cli/AgentApplicationTest.java client/core/src/main/java/com/redhat/thermostat/client/internal/Main.java client/core/src/test/java/com/redhat/thermostat/client/internal/MainTest.java common/core/src/main/java/com/redhat/thermostat/common/dao/DAOFactory.java common/core/src/main/java/com/redhat/thermostat/common/dao/MongoDAOFactory.java common/core/src/test/java/com/redhat/thermostat/common/dao/MongoDAOFactoryTest.java launcher/src/main/java/com/redhat/thermostat/launcher/internal/DbServiceImpl.java launcher/src/test/java/com/redhat/thermostat/launcher/internal/DbServiceTest.java
diffstat 9 files changed, 403 insertions(+), 50 deletions(-) [+]
line wrap: on
line diff
--- a/agent/cli/src/main/java/com/redhat/thermostat/agent/cli/AgentApplication.java	Mon Oct 22 17:34:00 2012 -0400
+++ b/agent/cli/src/main/java/com/redhat/thermostat/agent/cli/AgentApplication.java	Mon Oct 22 18:24:19 2012 -0400
@@ -41,6 +41,7 @@
 import java.util.logging.Logger;
 
 import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
 
 import sun.misc.Signal;
 import sun.misc.SignalHandler;
@@ -70,24 +71,30 @@
 import com.redhat.thermostat.common.storage.StorageProvider;
 import com.redhat.thermostat.common.tools.BasicCommand;
 import com.redhat.thermostat.common.utils.LoggingUtils;
-import com.redhat.thermostat.common.utils.OSGIUtils;
 
 @SuppressWarnings("restriction")
 public final class AgentApplication extends BasicCommand {
 
     private static final String NAME = "agent";
 
+    private final BundleContext bundleContext;
+    private final ConfigurationCreator configurationCreator;
+    private final DAOFactoryCreator daoFactoryCreator;
+
     private AgentStartupConfiguration configuration;
     private AgentOptionParser parser;
-    
-    private BundleContext bundleContext;
-    
+
     public AgentApplication(BundleContext bundleContext) {
+        this(bundleContext, new ConfigurationCreator(), new DAOFactoryCreator());
+    }
+
+    AgentApplication(BundleContext bundleContext, ConfigurationCreator configurationCreator, DAOFactoryCreator daoFactoryCreator) {
         this.bundleContext = bundleContext;
+        this.configurationCreator = configurationCreator;
+        this.daoFactoryCreator = daoFactoryCreator;
     }
     
     private void parseArguments(Arguments args) throws InvalidConfigurationException {
-        configuration = AgentConfigsUtils.createAgentConfigs();
         parser = new AgentOptionParser(configuration, args);
         parser.parse();
     }
@@ -106,8 +113,7 @@
         }
         final Logger logger = LoggingUtils.getLogger(AgentApplication.class);
 
-        StorageProvider connProv = new MongoStorageProvider(configuration);
-        final DAOFactory daoFactory = new MongoDAOFactory(connProv);
+        final DAOFactory daoFactory = daoFactoryCreator.create(configuration);
         TimerFactory timerFactory = new ThreadPoolTimerFactory(1);
         ApplicationContext.getInstance().setTimerFactory(timerFactory);
 
@@ -139,7 +145,8 @@
         connection.connect();
         logger.fine("Connecting to storage...");
 
-        final ConfigurationServer configServer = OSGIUtils.getInstance().getService(ConfigurationServer.class);
+        ServiceReference configServiceRef = bundleContext.getServiceReference(ConfigurationServer.class.getName());
+        final ConfigurationServer configServer = (ConfigurationServer) bundleContext.getService(configServiceRef);
         configServer.startListening(configuration.getConfigListenAddress());
         
         BackendRegistry backendRegistry = null;
@@ -186,6 +193,8 @@
     @Override
     public void run(CommandContext ctx) throws CommandException {
         try {
+            configuration = configurationCreator.create();
+
             parseArguments(ctx.getArguments());
             if (!parser.isHelp()) {
                 runAgent(ctx);
@@ -231,4 +240,18 @@
         
     }
 
+    static class ConfigurationCreator {
+        public AgentStartupConfiguration create() throws InvalidConfigurationException {
+            return AgentConfigsUtils.createAgentConfigs();
+        }
+    }
+
+    static class DAOFactoryCreator {
+        public DAOFactory create(AgentStartupConfiguration config) {
+            StorageProvider connProv = new MongoStorageProvider(config);
+            final DAOFactory daoFactory = new MongoDAOFactory(connProv);
+            return daoFactory;
+        }
+    }
+
 }
--- a/agent/cli/src/test/java/com/redhat/thermostat/agent/cli/AgentApplicationTest.java	Mon Oct 22 17:34:00 2012 -0400
+++ b/agent/cli/src/test/java/com/redhat/thermostat/agent/cli/AgentApplicationTest.java	Mon Oct 22 18:24:19 2012 -0400
@@ -38,27 +38,66 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
-import org.osgi.framework.BundleContext;
+import org.mockito.ArgumentCaptor;
+
+import com.redhat.thermostat.agent.cli.AgentApplication.ConfigurationCreator;
+import com.redhat.thermostat.agent.cli.AgentApplication.DAOFactoryCreator;
+import com.redhat.thermostat.agent.config.AgentStartupConfiguration;
+import com.redhat.thermostat.common.cli.Arguments;
+import com.redhat.thermostat.common.cli.CommandContext;
+import com.redhat.thermostat.common.cli.CommandException;
+import com.redhat.thermostat.common.config.InvalidConfigurationException;
+import com.redhat.thermostat.common.dao.DAOFactory;
+import com.redhat.thermostat.common.storage.Connection;
+import com.redhat.thermostat.common.storage.Connection.ConnectionListener;
+import com.redhat.thermostat.common.storage.Connection.ConnectionStatus;
+import com.redhat.thermostat.test.StubBundleContext;
 
 public class AgentApplicationTest {
 
     // TODO: Test i18nized versions when they come.
 
+    private StubBundleContext context;
+    private DAOFactory daoFactory;
+    private Connection connection;
+
     private AgentApplication agent;
 
-    private BundleContext context;
+    private ArgumentCaptor<ConnectionListener> listenerCaptor;
     
     @Before
-    public void setUp() {
+    public void setUp() throws InvalidConfigurationException {
+        
+        context = new StubBundleContext();
         
-        context = mock(BundleContext.class);
-        
-        agent = new AgentApplication(context);
+        AgentStartupConfiguration config = mock(AgentStartupConfiguration.class);
+        when(config.getDBConnectionString()).thenReturn("test string; please ignore");
+
+        ConfigurationCreator configCreator = mock(ConfigurationCreator.class);
+        when(configCreator.create()).thenReturn(config);
+
+        listenerCaptor = ArgumentCaptor.forClass(ConnectionListener.class);
+
+        connection = mock(Connection.class);
+        doNothing().when(connection).addListener(listenerCaptor.capture());
+
+        daoFactory = mock(DAOFactory.class);
+        when(daoFactory.getConnection()).thenReturn(connection);
+
+        DAOFactoryCreator daoCreator = mock(DAOFactoryCreator.class);
+        when(daoCreator.create(config)).thenReturn(daoFactory);
+
+        agent = new AgentApplication(context, configCreator, daoCreator);
     }
 
     @After
@@ -77,4 +116,34 @@
         assertNotNull(agent.getDescription());
         assertNotNull(agent.getUsage());
     }
+
+    @Test
+    public void testAgentStartupRegistersDAOs() throws CommandException {
+
+        doThrow(new ThatsAllThatWeCareAbout()).when(connection).connect();
+
+        Arguments args = mock(Arguments.class);
+        CommandContext commandContext = mock(CommandContext.class);
+
+        when(commandContext.getArguments()).thenReturn(args);
+
+        try {
+            agent.run(commandContext);
+            fail("not supposed to get here");
+        } catch (ThatsAllThatWeCareAbout done) {
+            // agent.run() is so convoluted that we just want to test a part of
+            // it
+        }
+
+        ConnectionListener listener = listenerCaptor.getValue();
+        listener.changed(ConnectionStatus.CONNECTED);
+
+        verify(daoFactory).registerDAOsAndStorageAsOSGiServices();
+    }
+
+    // FIXME test the rest of AgentApplication
+
+    private static class ThatsAllThatWeCareAbout extends RuntimeException {
+
+    }
 }
--- a/client/core/src/main/java/com/redhat/thermostat/client/internal/Main.java	Mon Oct 22 17:34:00 2012 -0400
+++ b/client/core/src/main/java/com/redhat/thermostat/client/internal/Main.java	Mon Oct 22 18:24:19 2012 -0400
@@ -84,15 +84,33 @@
 
     private static final Logger logger = LoggingUtils.getLogger(Main.class);
 
+    private OSGIUtils serviceProvider;
     private UiFacadeFactory uiFacadeFactory;
     private DAOFactory daoFactory;
     
     public Main(Keyring keyring, UiFacadeFactory uiFacadeFactory, String[] args) {
-        this.uiFacadeFactory = uiFacadeFactory;
-        setUp(keyring);
+        ClientPreferences prefs = new ClientPreferences(keyring);
+        StartupConfiguration config = new ConnectionConfiguration(prefs);
+        StorageProvider connProv = new MongoStorageProvider(config);
+
+        DAOFactory daoFactory = new MongoDAOFactory(connProv);
+        TimerFactory timerFactory = new ThreadPoolTimerFactory(1);
+
+        init(OSGIUtils.getInstance(), uiFacadeFactory, daoFactory, timerFactory);
     }
 
-    void run() {
+    Main(OSGIUtils serviceProvider, UiFacadeFactory uiFacadeFactory, DAOFactory daoFactory, TimerFactory timerFactory) {
+        init(serviceProvider, uiFacadeFactory, daoFactory, timerFactory);
+    }
+
+    private void init(OSGIUtils serviceProvider, UiFacadeFactory uiFacadeFactory, DAOFactory daoFactory, TimerFactory timerFactory) {
+        this.serviceProvider = serviceProvider;
+        this.uiFacadeFactory = uiFacadeFactory;
+        this.daoFactory = daoFactory;
+        ApplicationContext.getInstance().setTimerFactory(timerFactory);
+    }
+
+    public void run() {
         EventQueue.invokeLater(new Runnable() {
 
             @Override
@@ -127,21 +145,9 @@
         }
     }
 
-    void setUp(Keyring keyring) {
-        ClientPreferences prefs = new ClientPreferences(keyring);
-        StartupConfiguration config = new ConnectionConfiguration(prefs);
-
-        StorageProvider connProv = new MongoStorageProvider(config);
-        daoFactory = new MongoDAOFactory(connProv);
-        TimerFactory timerFactory = new ThreadPoolTimerFactory(1);
-        ApplicationContext.getInstance().setTimerFactory(timerFactory);
-    }
-        
     private void showGui() {
-        
-        ApplicationService appSrv = OSGIUtils.getInstance().getService(ApplicationService.class);
+        ApplicationService appSrv = serviceProvider.getService(ApplicationService.class);
         final ExecutorService service = appSrv.getApplicationExecutor();
-        
         service.execute(new ConnectorSetup(service));
     }
     
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/core/src/test/java/com/redhat/thermostat/client/internal/MainTest.java	Mon Oct 22 18:24:19 2012 -0400
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat 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 Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.client.internal;
+
+import static org.mockito.Matchers.isA;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.concurrent.ExecutorService;
+
+import javax.swing.SwingUtilities;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import com.redhat.thermostat.client.osgi.service.ApplicationService;
+import com.redhat.thermostat.client.ui.MainWindowController;
+import com.redhat.thermostat.client.ui.UiFacadeFactory;
+import com.redhat.thermostat.common.TimerFactory;
+import com.redhat.thermostat.common.dao.DAOFactory;
+import com.redhat.thermostat.common.storage.Connection;
+import com.redhat.thermostat.common.storage.Connection.ConnectionListener;
+import com.redhat.thermostat.common.storage.Connection.ConnectionStatus;
+import com.redhat.thermostat.common.utils.OSGIUtils;
+
+public class MainTest {
+
+    private ExecutorService executorService;
+    private OSGIUtils serviceProvider;
+
+    private MainWindowController mainWindowController;
+    private UiFacadeFactory uiFactory;
+
+    private Connection connection;
+    private ArgumentCaptor<ConnectionListener> connectionListenerCaptor;
+
+    private DAOFactory daoFactory;
+
+    private TimerFactory timerFactory;
+
+    @Before
+    public void setUp() {
+        ApplicationService appService = mock(ApplicationService.class);
+
+        executorService = mock(ExecutorService.class);
+        doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                Runnable runnable = (Runnable) invocation.getArguments()[0];
+                runnable.run();
+                return null;
+            }
+        }).when(executorService).execute(isA(Runnable.class));
+
+        when(appService.getApplicationExecutor()).thenReturn(executorService);
+
+        serviceProvider = mock(OSGIUtils.class);
+        when(serviceProvider.getService(ApplicationService.class)).thenReturn(appService);
+
+        mainWindowController = mock(MainWindowController.class);
+
+        uiFactory = mock(UiFacadeFactory.class);
+        when(uiFactory.getMainWindow()).thenReturn(mainWindowController);
+
+        connection = mock(Connection.class);
+        connectionListenerCaptor = ArgumentCaptor.forClass(ConnectionListener.class);
+        doNothing().when(connection).addListener(connectionListenerCaptor.capture());
+
+        daoFactory = mock(DAOFactory.class);
+        when(daoFactory.getConnection()).thenReturn(connection);
+
+        timerFactory = mock(TimerFactory.class);
+    }
+
+    /**
+     * Handle all outstanding EDT events by posting a no-op event and waiting
+     * until it completes.
+     */
+    private void handleAllEdtEvents() throws Exception {
+        SwingUtilities.invokeAndWait(new Runnable() {
+            @Override
+            public void run() {
+                /* NO-OP */
+            }
+        });
+    }
+
+    @Test
+    public void verifyRunWaitsForShutdown() throws Exception {
+        Main main = new Main(serviceProvider, uiFactory, daoFactory, timerFactory);
+
+        main.run();
+
+        handleAllEdtEvents();
+
+        verify(uiFactory).awaitShutdown();
+    }
+
+    @Test
+    public void verifyConnectionIsMade() throws Exception {
+        Main main = new Main(serviceProvider, uiFactory, daoFactory, timerFactory);
+
+        main.run();
+
+        handleAllEdtEvents();
+
+        verify(connection).connect();
+
+    }
+
+    @Test
+    public void verifySuccessfulConnectionTriggersMainWindowToBeShown() throws Exception {
+        Main main = new Main(serviceProvider, uiFactory, daoFactory, timerFactory);
+
+        main.run();
+
+        handleAllEdtEvents();
+
+        ConnectionListener connectionListener = connectionListenerCaptor.getValue();
+        connectionListener.changed(ConnectionStatus.CONNECTED);
+
+        handleAllEdtEvents();
+
+        verify(mainWindowController).showMainMainWindow();
+    }
+
+    @Test
+    public void verifySuccessfulConnectionRegistersDAOs() throws Exception {
+
+        Main main = new Main(serviceProvider, uiFactory, daoFactory, timerFactory);
+
+        main.run();
+
+        handleAllEdtEvents();
+
+        ConnectionListener connectionListener = connectionListenerCaptor.getValue();
+        connectionListener.changed(ConnectionStatus.CONNECTED);
+
+        handleAllEdtEvents();
+
+        verify(daoFactory).registerDAOsAndStorageAsOSGiServices();
+    }
+
+    @Ignore("this prompts the user with some gui")
+    @Test
+    public void verifyFailedConnectionTriggersShutdown() throws Exception {
+
+        Main main = new Main(serviceProvider, uiFactory, daoFactory, timerFactory);
+
+        main.run();
+
+        handleAllEdtEvents();
+
+        ConnectionListener connectionListener = connectionListenerCaptor.getValue();
+        connectionListener.changed(ConnectionStatus.FAILED_TO_CONNECT);
+
+        handleAllEdtEvents();
+
+        verify(uiFactory).shutdown();
+    }
+}
--- a/common/core/src/main/java/com/redhat/thermostat/common/dao/DAOFactory.java	Mon Oct 22 17:34:00 2012 -0400
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/DAOFactory.java	Mon Oct 22 18:24:19 2012 -0400
@@ -71,5 +71,6 @@
     public HeapDAO getHeapDAO();
 
     public void registerDAOsAndStorageAsOSGiServices();
+    public void unregisterDAOsAndStorageAsOSGiServices();
 
 }
--- a/common/core/src/main/java/com/redhat/thermostat/common/dao/MongoDAOFactory.java	Mon Oct 22 17:34:00 2012 -0400
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/MongoDAOFactory.java	Mon Oct 22 18:24:19 2012 -0400
@@ -36,16 +36,30 @@
 
 package com.redhat.thermostat.common.dao;
 
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceRegistration;
+
 import com.redhat.thermostat.common.storage.Connection;
+import com.redhat.thermostat.common.storage.Storage;
 import com.redhat.thermostat.common.storage.StorageProvider;
-import com.redhat.thermostat.common.storage.Storage;
-import com.redhat.thermostat.common.utils.OSGIUtils;
 
 public class MongoDAOFactory implements DAOFactory {
 
     private final Storage storage;
+    private final BundleContext bundleContext;
+    private final List<ServiceRegistration> registeredServices = new ArrayList<>();
 
     public MongoDAOFactory(StorageProvider prov) {
+        this(FrameworkUtil.getBundle(MongoDAOFactory.class).getBundleContext(), prov);
+    }
+
+    public MongoDAOFactory(BundleContext bundleContext, StorageProvider prov) {
+        this.bundleContext = bundleContext;
         storage = prov.createStorage();
     }
 
@@ -137,23 +151,35 @@
 
     @Override
     public void registerDAOsAndStorageAsOSGiServices() {
-        OSGIUtils registerer = OSGIUtils.getInstance();
+        registerAndRecordService(Storage.class, getStorage());
+
+        registerAndRecordService(AgentInfoDAO.class, getAgentInfoDAO());
+        registerAndRecordService(BackendInfoDAO.class, getBackendInfoDAO());
 
-        registerer.registerService(Storage.class, getStorage());
-
-        registerer.registerService(AgentInfoDAO.class, getAgentInfoDAO());
-        registerer.registerService(BackendInfoDAO.class, getBackendInfoDAO());
+        registerAndRecordService(HostInfoDAO.class, getHostInfoDAO());
+        registerAndRecordService(NetworkInterfaceInfoDAO.class, getNetworkInterfaceInfoDAO());
+        registerAndRecordService(CpuStatDAO.class, getCpuStatDAO());
+        registerAndRecordService(MemoryStatDAO.class, getMemoryStatDAO());
 
-        registerer.registerService(HostInfoDAO.class, getHostInfoDAO());
-        registerer.registerService(NetworkInterfaceInfoDAO.class, getNetworkInterfaceInfoDAO());
-        registerer.registerService(CpuStatDAO.class, getCpuStatDAO());
-        registerer.registerService(MemoryStatDAO.class, getMemoryStatDAO());
+        registerAndRecordService(VmInfoDAO.class, getVmInfoDAO());
+        registerAndRecordService(VmClassStatDAO.class, getVmClassStatsDAO());
+        registerAndRecordService(VmCpuStatDAO.class, getVmCpuStatDAO());
+        registerAndRecordService(VmGcStatDAO.class, getVmGcStatDAO());
+        registerAndRecordService(VmMemoryStatDAO.class, getVmMemoryStatDAO());
+        registerAndRecordService(HeapDAO.class, getHeapDAO());
+    }
 
-        registerer.registerService(VmInfoDAO.class, getVmInfoDAO());
-        registerer.registerService(VmClassStatDAO.class, getVmClassStatsDAO());
-        registerer.registerService(VmCpuStatDAO.class, getVmCpuStatDAO());
-        registerer.registerService(VmGcStatDAO.class, getVmGcStatDAO());
-        registerer.registerService(VmMemoryStatDAO.class, getVmMemoryStatDAO());
-        registerer.registerService(HeapDAO.class, getHeapDAO());
+    private <K> void registerAndRecordService(Class<K> serviceType, K serviceImplementation) {
+        registeredServices.add(bundleContext.registerService(serviceType, serviceImplementation, null));
     }
+
+    public void unregisterDAOsAndStorageAsOSGiServices() {
+        Iterator<ServiceRegistration> iter = registeredServices.iterator();
+        while (iter.hasNext()) {
+            ServiceRegistration registration = iter.next();
+            registration.unregister();
+            iter.remove();
+        }
+    }
+
 }
--- a/common/core/src/test/java/com/redhat/thermostat/common/dao/MongoDAOFactoryTest.java	Mon Oct 22 17:34:00 2012 -0400
+++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/MongoDAOFactoryTest.java	Mon Oct 22 18:24:19 2012 -0400
@@ -36,6 +36,7 @@
 
 package com.redhat.thermostat.common.dao;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertSame;
 import static org.mockito.Mockito.mock;
@@ -47,18 +48,22 @@
 import com.redhat.thermostat.common.storage.Connection;
 import com.redhat.thermostat.common.storage.Storage;
 import com.redhat.thermostat.common.storage.StorageProvider;
+import com.redhat.thermostat.test.StubBundleContext;
 
 public class MongoDAOFactoryTest {
 
+    private StubBundleContext bundleContext;
     private Storage storage;
     private Connection connection;
     private StorageProvider provider;
     private DAOFactory daoFactory;
-    HostRef hostRef;
-    VmRef vmRef;
+    private HostRef hostRef;
+    private VmRef vmRef;
 
     @Before
     public void setUp() {
+        bundleContext = new StubBundleContext();
+
         storage = mock(Storage.class);
         connection = mock(Connection.class);
         when(storage.getConnection()).thenReturn(connection);
@@ -67,7 +72,7 @@
         when(provider.createStorage()).thenReturn(storage);
         hostRef = mock(HostRef.class);
         vmRef = mock(VmRef.class);
-        daoFactory = new MongoDAOFactory(provider);
+        daoFactory = new MongoDAOFactory(bundleContext, provider);
     }
 
     @Test
@@ -140,4 +145,23 @@
         HeapDAO dao = daoFactory.getHeapDAO();
         assertNotNull(dao);
     }
+
+    @Test
+    public void testServiceRegistration() {
+        assertEquals(0, bundleContext.getAllServices().size());
+
+        daoFactory.registerDAOsAndStorageAsOSGiServices();
+
+        // currently 12 DAOs and Storage are registered
+        assertEquals(13, bundleContext.getAllServices().size());
+    }
+
+    @Test
+    public void testServiceDeregistration() {
+        daoFactory.registerDAOsAndStorageAsOSGiServices();
+        daoFactory.unregisterDAOsAndStorageAsOSGiServices();
+
+        assertEquals(0, bundleContext.getAllServices().size());
+        assertEquals(0, bundleContext.getServiceListeners().size());
+    }
 }
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/DbServiceImpl.java	Mon Oct 22 17:34:00 2012 -0400
+++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/DbServiceImpl.java	Mon Oct 22 18:24:19 2012 -0400
@@ -67,6 +67,7 @@
     }
     
     public void disconnect() throws ConnectionException {
+        daoFactory.unregisterDAOsAndStorageAsOSGiServices();
         daoFactory.getConnection().disconnect();
     }
     
--- a/launcher/src/test/java/com/redhat/thermostat/launcher/internal/DbServiceTest.java	Mon Oct 22 17:34:00 2012 -0400
+++ b/launcher/src/test/java/com/redhat/thermostat/launcher/internal/DbServiceTest.java	Mon Oct 22 18:24:19 2012 -0400
@@ -92,6 +92,7 @@
     public void testDisconnect() {
         dbService.disconnect();
 
+        verify(daoFactory).unregisterDAOsAndStorageAsOSGiServices();
         verify(connection).disconnect();
     }