Testing with mockito on OpenMRS

Hello, I have just created an api end point that enables one to install a module by passing the url where the omod for installation is located. It uses ModuleUtil when downloading the omod then goes on to install the module. I am trying to test the method that handles the request but am having issues with creating a mock object of ModuleUtil. I have read through https://wiki.openmrs.org/display/docs/Mock+Doc, but it was not of much help. My implementation is at this location, and the error log after running my tests is at https://pastebin.com/DDsLGuzs.

@dkayiwa, @raff

@malmike did you see this:

1. you stub either of: final/private/equals()/hashCode() methods.
   Those methods *cannot* be stubbed/verified.
2. inside when() you don't call method on mock but on some other object.
3. the parent of the mocked class is not public.
   It is a limitation of the mock engine.

Also it would help others to point to the actual test. Even to the precise line (since forked repositories cannot be searched).

@mksd I have updated the link, to directly go to the test. Am still trying to understand the snippet you have just sent, but I have not done much with mockito so I will need more explanation.

It’s now pointing to the commit, which is better. But it still doesn’t point to the actual test case or line that fails. Have a look at this and point us to the exact place to look at.

Also have you seen this:

1. you stub either of: final/private/equals()/hashCode() methods.
   Those methods *cannot* be stubbed/verified.
2. inside when() you don't call method on mock but on some other object.
3. the parent of the mocked class is not public.
   It is a limitation of the mock engine.

@mksd I’ve updated the link

@mksd So the method am trying to mock is a static method that does not necessarily need an object to be created to be used, but can be called by the class without being instantiated. How can I go about mocking it.

That depends. Here is an example of mocking a static method using PowerMockRunner. However I think the catch is that you can’t mix context sensitive tests and using PowerMockRunner. So you might be doomed.

I’m not sure what you are up to but your commit above seems to suggest that there is some module loading going on in your context sensitive test. If that’s the case then the @StartModule annotation is supposed to trigger the loading of a module in a context sensitive test. You might want to try it out and report back.
Example here in the OpenMRS Core test code base.

The task am trying to test which is at this location, involves downloading the module on to the server using a static method in ModuleUtil, then loading the module and starting it. What I want to mock out is the downloading of the module. Also am not sure how @StartModule can be used for my specific task from the description

How far can you go without mocking ModuleUtil? That’s what I would try as far as possible.

Actually, I suggest that you also mock loading the module. That is very expensive, and unnecessary for this test, since you should trust it works from openmrs core tests.

Having a (very) quick look at ModuleUtil I see that it basically just calls ModuleFactory. In the Address Hierarchy module (‘AH’) I could actually get to mock loading modules to a certain extent. See here.
In AH that line was enough to make the whole environment behave like if the module ‘exti18n’ was loaded and started. @malmike you could try something like that.

I had to do it in the constructor of the test class in order for things to happens even before Spring starts firing.

I have applied ModuleFactory but the fact that I still have to pass a URL it does not use the mock test module. I have a log of the error generated after running the test with the new changes here. And I included it in the tests here

Well right now you have an assertion error, meaning that the whole thing went through. But of course the assert on mockModuleFactory fails since this mock object is never used in the “real” code.

So what’s your starting point upon setting up the test case, is it that the mock module should be loaded (but not installed yet)?
If yes then pay attention to the fact that I gave you a snippet that was starting a mock module, so you would have to adapt that. Also you should be able to do this in the setup method. The reason why I had to do this in a constructor in AH was because of Spring loading and the use of OpenmrsProfile, but that doesn’t apply to you.

Since your code seems to go through, then extract whatever is that you need to extract from ModuleUtil after the POST request was handled, and make your assertions on the objects gotten from it.


P.S. On a side note, you should respect camel case in your methods and variables names: getModuleUuid() not getModuleuuid(), getInstallUri() not getInstalluri() … etc (same for variables).

@mksd Thanks for the help. I was able to create a test, but did not mock the ModuleUtil class. You can review my PR here and point out if there are any things I should change.