Unit Tests Cannot Load Application Context

I am failing to run unit test because the application context cannot be loaded due to a nested spring bean error https://gist.github.com/ssmusoke/f7a461a1e4c6a7e0479da83ee9447431

My question: What is needed to be able to load the application context as there is no guide for that in the wiki

From the stack trace it looks like you’re missing certain dependencies on the classpath e.g provider management api

And htmlformentry api looks like it’s missing too

In theory, when writing context sensitive tests for a module that depends on another, you pretty much have to add all the dependencies of the other module too to your test classpath, you can get the list of the other module’s dependencies from its config.xml file.

@wyclif How do I resolve the error attached in the gist https://gist.github.com/ssmusoke/0cba034d3bb97738029a4b4dd6b1d7e9

My Rest configuration is below - and is included in the api pom of my project ` org.openmrs.module webservices.rest-omod-common ${webservices.restModuleVersion} provided

	<dependency>
		<groupId>org.openmrs.module</groupId>
		<artifactId>webservices.rest-omod-common</artifactId>
		<version>${webservices.restModuleVersion}</version>
		<type>test-jar</type>
		<scope>test</scope>
	</dependency>

	<dependency>
		<groupId>org.openmrs.module</groupId>
		<artifactId>webservices.rest-omod-1.8</artifactId>
		<version>${webservices.restModuleVersion}</version>
		<scope>test</scope>
	</dependency>`

From the error message, you can see that spring is unable to load the RestService class, that class is in the omod-common sub project, you added the test jar dependency but didn’t add the omod-common jar dependency too, can you add it with no type (because jar is the default) and scope set to provided as below.

<dependency>
         <groupId>org.openmrs.module</groupId>
         <artifactId>webservices.rest-omod-common</artifactId>
         <version>${webservices.restModuleVersion}</version>
         <!-- This can be set test if you only need it for testing purposes -->
         <scope>provided</scope>
    </dependency>

I’ve also noticed that you probably just copied the dependencies from the module I referred you to, you should only be adding dependencies you need which I think is the omod-common jar. My assumption is that you don’t need the omod-1.8 test jar, in my module I needed it for testing purposes but I doubt you need it, getting rid of it might solve the issue you’re running into.

@wyclif adding the 1.8 version removes an error with creating a bean of org.springframework.oxm.xstream.XStreamMarshaller , I had not copied the webservices.rest-omod-common dependency, but it is included in the pom file with the error.

The strange thing is that in the error the bean that fails to load is of org.openmrs.module.webservices.rest.web.v1_0.controller.openmrs1_8.SessionController1_8.restService - does that have any significance?

Because it fixes it doesn’t mean it is the correct thing to do, that omod-1.8 jar file actually doesn’t contain the XStreamMarshaller class, the marshaller class is only getting visible because it’s contained in another dependency that is getting included transitively, removing that omod-1.8 test jar and adding omod-1.8 jar could possibly also fix it. The only reason you would need the omod-1.8 test jar is because it contains some test resources and classes that you might need for your tests.

I earlier mentioned why SessionController1_8 fails to load, adding the omod-1.8 jar should fix it because it is what contains the RestService class that spring is trying to autowire into the SessionController1_8 class

@wyclif the configuration below gives me a class not found error for MainResourceControllerTest which is found in the omod-common test classes. However when I add the omod-common test-jar the restService in the omod-1.8 cannot be resolved. Looks like I cannot have omod-common test-jar and omod-1.8 jars at the same time - any ideas

 `<dependency>
		<groupId>org.openmrs.module</groupId>
		<artifactId>webservices.rest-omod-common</artifactId>
		<version>${webservices.restModuleVersion}</version>
		<scope>provided</scope>
	</dependency>

	<dependency>
		<groupId>org.openmrs.module</groupId>
		<artifactId>webservices.rest-omod-1.8</artifactId>
		<version>${webservices.restModuleVersion}</version>
		<scope>provided</scope>
	</dependency>

	<dependency>
		<groupId>org.openmrs.module</groupId>
		<artifactId>webservices.rest-omod-1.8</artifactId>
		<version>${webservices.restModuleVersion}</version>
		<type>test-jar</type>
		<scope>test</scope>
	</dependency>

`

In theory, when you get a class not found exception, it means you’re missing the dependency that contains that class on the classpath, in this case you’re missing the omod-common test jar and you need to add it. By the way, do you really need the omod-1.8 test jar? When you remove it, doesn’t the build and tests pass?

@wyclif my findings are as follows:

  1. rest-omod-1.8 includes rest-common as a dependency in its pom file so no need to explicitly add it

  2. adding rest-omod-common test jar causes the org.openmrs.module.webservices.rest.web.v1_0.controller.openmrs1_8.SessionController1_8.restService class not to be found

  3. removing rest-omod-common test jar causes the class not to be found org/openmrs/module/webservices/rest/web/v1_0/controller/MainResourceControllerTest

You need to add omod-common test jar otherwise you will keep getting that class not found exception

I meant omod-common test jar

@wyclif adding the omod-common test jar file causes the 1.8 version of the restService class not to be found

Then you need to address the rest service class instead of removing the dependency. A quick glance at the code, I see you’re adding web components to the api sub project which is wrong, can you first move them to the omod sub project?

@wyclif The test is for the activator loading the forms which are web components - do I move the test to the OMOD when the files are in the api - project

Then I would suggest you move the activator to the omod subproject.

The module appears not to be well set up to me, I see so many XXX-omod dependencies in the api sub project, in theory that should not be the case. And I believe the HtmlFormEntry related classes and tests should be in the omod sub project. And since your test is web related you need to extend BaseModuleWebContextSensitiveTest instead of BaseModuleContextSensitiveTest otherwise you will get class not found exceptions. The only dependency from the REST module you will need is omod-common jar. Since you’re moving things to omod sub project, you will also have to add more other module dependencies to the omod project from the api probably with a test scope

Add the snippet below to the test before you call the initializer

ModuleResourceProvider rp = Mockito.mock(ModuleResourceProvider.class);
Mockito.when(rp.getResource(Mockito.anyString())).thenReturn(new File("omod/src/main/webapp/resources/htmlforms"));
final ResourceFactory resourceFactory = Context.getRegisteredComponent("coreResourceFactory", ResourceFactory.class);
resourceFactory.addResourceProvider("aijar", rp);

This is better

ModuleResourceProvider rp = Mockito.mock(ModuleResourceProvider.class);
Mockito.when(rp.getResource(Mockito.eq("htmlforms/"))).thenReturn(new File("omod/src/main/webapp/resources/htmlforms"));
final ResourceFactory resourceFactory = Context.getRegisteredComponent("coreResourceFactory", ResourceFactory.class);
resourceFactory.addResourceProvider("aijar", rp);