Skip to content

Commit

Permalink
Adding classes that support testing module activator methods that
Browse files Browse the repository at this point in the history
require refreshing of the spring application context - TRUNK-4134
  • Loading branch information
dkayiwa committed Nov 13, 2013
1 parent 259d1b0 commit 2d3b5d5
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 30 deletions.
50 changes: 50 additions & 0 deletions api/src/test/java/org/openmrs/module/BaseModuleActivatorTest.java
@@ -0,0 +1,50 @@
/**
* The contents of this file are subject to the OpenMRS Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://license.openmrs.org
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* Copyright (C) OpenMRS, LLC. All Rights Reserved.
*/
package org.openmrs.module;

import org.junit.Before;
import org.openmrs.test.BaseContextSensitiveTest;

/**
* Has functionality commonly used by unit tests for module activator
*/
public abstract class BaseModuleActivatorTest extends BaseContextSensitiveTest {

protected static final String MODULE1_ID = "test1";

protected static final String MODULE2_ID = "test2";

protected static final String MODULE3_ID = "test3";

protected ModuleTestData moduleTestData;

@Before
public void beforeEachTest() throws Exception {
moduleTestData = ModuleTestData.getInstance();

This comment has been minimized.

Copy link
@wluyima

wluyima Nov 13, 2013

Member

I thought you said you would change this since it is not necessary to call it all the time, another option would be actually to assign it during declaration on line 30 above

This comment has been minimized.

Copy link
@dkayiwa

dkayiwa Nov 13, 2013

Author Member

oh ya. will change it.


ModuleUtil.shutdown();

init();

String modulesToLoad = "org/openmrs/module/include/test3-1.0-SNAPSHOT.omod org/openmrs/module/include/test1-1.0-SNAPSHOT.omod org/openmrs/module/include/test2-1.0-SNAPSHOT.omod";
runtimeProperties.setProperty(ModuleConstants.RUNTIMEPROPERTY_MODULE_LIST_TO_LOAD, modulesToLoad);
ModuleUtil.startup(runtimeProperties);
}

protected void init() {
moduleTestData.init(MODULE1_ID);
moduleTestData.init(MODULE2_ID);
moduleTestData.init(MODULE3_ID);
}
}
35 changes: 5 additions & 30 deletions api/src/test/java/org/openmrs/module/ModuleActivatorTest.java
Expand Up @@ -15,32 +15,13 @@

import static org.junit.Assert.assertTrue;

import org.junit.Before;
import org.junit.Test;
import org.openmrs.test.BaseContextSensitiveTest;

public class ModuleActivatorTest extends BaseContextSensitiveTest {

private static final String MODULE1_ID = "test1";

private static final String MODULE2_ID = "test2";

private static final String MODULE3_ID = "test3";

private ModuleTestData moduleTestData;

@Before
public void beforeEachTest() throws Exception {
moduleTestData = ModuleTestData.getInstance();

ModuleUtil.shutdown();

init();

String modulesToLoad = "org/openmrs/module/include/test3-1.0-SNAPSHOT.omod org/openmrs/module/include/test1-1.0-SNAPSHOT.omod org/openmrs/module/include/test2-1.0-SNAPSHOT.omod";
runtimeProperties.setProperty(ModuleConstants.RUNTIMEPROPERTY_MODULE_LIST_TO_LOAD, modulesToLoad);
ModuleUtil.startup(runtimeProperties);
}
/**
* Tests methods of the module activator that do not require refreshing of the spring applications
* context. For those that require refreshing, see WebModuleActivatorTest
*/
public class ModuleActivatorTest extends BaseModuleActivatorTest {

@Test
public void shouldCallWillStartOnStartup() throws Exception {
Expand Down Expand Up @@ -172,10 +153,4 @@ public void shouldExcludePrevouslyStoppedModules() {
assertTrue(moduleTestData.getStoppedCallCount(MODULE2_ID) == 1);
assertTrue(moduleTestData.getStoppedCallCount(MODULE3_ID) == 1);
}

public void init() {
moduleTestData.init(MODULE1_ID);
moduleTestData.init(MODULE2_ID);
moduleTestData.init(MODULE3_ID);
}
}
39 changes: 39 additions & 0 deletions web/src/test/java/org/openmrs/web/test/TestContextLoader.java
@@ -0,0 +1,39 @@
/**
* The contents of this file are subject to the OpenMRS Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://license.openmrs.org
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* Copyright (C) OpenMRS, LLC. All Rights Reserved.
*/
package org.openmrs.web.test;

import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.support.AbstractContextLoader;

/**
* The only reason why i created this class is to be able to create an application context which can
* be refreshed multiple times, unlike the default GenericApplicationContext which can be refreshed

This comment has been minimized.

Copy link
@wluyima

wluyima Nov 13, 2013

Member

Couldn't you use AbstractRefreshableApplicationContext

This comment has been minimized.

Copy link
@dkayiwa

dkayiwa Nov 13, 2013

Author Member

I do not know how to change the default to any other without using a context loader.

This comment has been minimized.

Copy link
@wluyima

wluyima Nov 13, 2013

Member

I thought ClassPathXmlApplicationContext is a subclass of AbstractRefreshableApplicationContext, so you should be able to refresh it

This comment has been minimized.

Copy link
@dkayiwa

dkayiwa Nov 14, 2013

Author Member

ClassPathXmlApplicationContext is not the default. So to use it, i had to create this context loader class. Did i get you right? :)

This comment has been minimized.

Copy link
@wluyima

wluyima Nov 14, 2013

Member

Ok, by the way it looks like your TestContextLoader creates an XmlWebApplicationContext which might explains why you were getting no class found exceptions due to it looking for web classes

This comment has been minimized.

Copy link
@dkayiwa

dkayiwa Nov 14, 2013

Author Member

I think the multiple commits could have confused you a bit. Am the one who changed the ClassPathXmlApplicationContext to XmlWebApplicationContext after realizing that WebModuleUtil.refreshApplicationContext expects it.

This comment has been minimized.

Copy link
@wluyima

wluyima Nov 14, 2013

Member

I can see that in the code you changed from ClassPathXmlApplicationContext to XmlWebApplicationContext, why? Do you have web classes in the test modules that you need to test against? Which class couldn't get loaded? May be you can fix so that it doesn't need to be loaded

* only once. This class is used for @ContextConfiguration in WebModuleActivatorTest
*/
public class TestContextLoader extends AbstractContextLoader {

public TestContextLoader() {
}

@Override
public final ConfigurableApplicationContext loadContext(String... locations) throws Exception {
return new ClassPathXmlApplicationContext(locations);
}

@Override
protected String getResourceSuffix() {
return "-context.xml";
}
}
49 changes: 49 additions & 0 deletions web/src/test/java/org/openmrs/web/test/WebModuleActivatorTest.java
@@ -0,0 +1,49 @@
/**
* The contents of this file are subject to the OpenMRS Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://license.openmrs.org
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* Copyright (C) OpenMRS, LLC. All Rights Reserved.
*/
package org.openmrs.web.test;

import static org.junit.Assert.assertTrue;

import org.junit.Test;
import org.openmrs.module.BaseModuleActivatorTest;
import org.openmrs.module.ModuleUtil;
import org.springframework.context.support.AbstractRefreshableApplicationContext;
import org.springframework.test.annotation.NotTransactional;
import org.springframework.test.context.ContextConfiguration;

/**
* ModuleActivator tests that need refreshing the spring application context. The only reason why i
* did not put these in the api projects's ModuleActivatorTest is because when the spring
* application context is refreshed, classes that the module references which are not in the api but
* web, will lead to ClassNotFoundException s, hence preventing the refresh. If you want to try this
* out, just put these tests in ModuleActivatorTest
*/
@ContextConfiguration(locations = { "classpath*:webModuleApplicationContext.xml" }, inheritLocations = true, loader = TestContextLoader.class)

This comment has been minimized.

Copy link
@wluyima

wluyima Nov 13, 2013

Member

But why would you reference web classes if these tests are testing the module engine which should be able to work outside a web environment. Technically these tests are testing logic in ModuleFactory and ModuleUtil and they don't reference any web classes

This comment has been minimized.

Copy link
@dkayiwa

dkayiwa Nov 14, 2013

Author Member

The only reason is that, modules have web classes which reference core web classes. I tried looking into workarounds but was taking too long without a solution. But if you can take these methods to the non web unit test class, ModuleActivatorTest, and have them work well, then you will have got a solution. :)

This comment has been minimized.

Copy link
@wluyima

wluyima Nov 14, 2013

Member

Why do you have to include webModuleApplicationContext.xml? Could be the reason you were getting class not found exceptions when you used the ClassPathXmlApplicationContext

public class WebModuleActivatorTest extends BaseModuleActivatorTest {

@Test
@NotTransactional
public void shouldCallWillRefreshContextAndContextRefreshedOnRefresh() throws Exception {

ModuleUtil.refreshApplicationContext((AbstractRefreshableApplicationContext) applicationContext, false, null);

This comment has been minimized.

Copy link
@wluyima

wluyima Nov 13, 2013

Member

Since you are calling ModuleUtil(not WebModuleUtil) which is in the api project, i think you should be able to test these without webModuleApplicationContext.xml and most likely not need this as a separate Test class

This comment has been minimized.

Copy link
@dkayiwa

dkayiwa Nov 14, 2013

Author Member

This results into refreshing the application context, where modules web classes reference core web classes and hence resulting into class not found exceptions.


assertTrue(moduleTestData.getWillRefreshContextCallCount(MODULE1_ID) == 1);
assertTrue(moduleTestData.getWillRefreshContextCallCount(MODULE2_ID) == 1);
assertTrue(moduleTestData.getWillRefreshContextCallCount(MODULE3_ID) == 1);

assertTrue(moduleTestData.getContextRefreshedCallCount(MODULE1_ID) == 1);
assertTrue(moduleTestData.getContextRefreshedCallCount(MODULE2_ID) == 1);
assertTrue(moduleTestData.getContextRefreshedCallCount(MODULE3_ID) == 1);
}
}

0 comments on commit 2d3b5d5

Please sign in to comment.