All,
I'm trying to do some unit testing in some archaic java code (no interfaces, no abstraction, etc.)
This is a servlet that uses a ServletContext (which I'm assuming is set up by Tomcat) and it has database information is set up in the web.xml/context.xml file. Now, I've figured out how to make a Fake ServletContext, but the code has
InitialContext _ic = new InitialContext();
all over the place (so it isn't feasible to replace it). I need to find a way to make a default InitialContext() able to do the _ic.lookup(val)
without throwing an exception.
I'm assuming there is some way that the context.xml is getting loaded, but how that magic works, I'm drawing a blank. Anyone have any ideas?
You can use PowerMock to mock construction of the InitialContext and control its behavior. Constructor Mocking is documented here.
PowerMock tests can be quite messy and complicated, refactoring is normally a better option.
A poor man's standalone implementation using no external libraries:
You could use a
switch
in the override of thelookup
method to return the expected value for each differentval
value passed to_ic.lookup(val)
throughout the legacy program.Take advantage of the fact that
InitialContext
uses an SPI to handle its creation. You can hook into its lifecycle by creating an implementation ofjavax.naming.spi.InitialContextFactory
and passing that to your tests via the system propertyjavax.naming.factory.initial
(Context.INTITIAL_CONTEXT_FACTORY
). It's simpler than it sounds.Given this class:
And this impl of
InitialContextFactory
:Creating an instance of
UseInitialContext
in a junit test withon the command line outputs
This is my object!!
(easy to set up in eclipse). I like Mockito for mocking and stubbing. I'd also recommend Micheal Feather's Working Effectively with Legacy Code if you deal with lots of legacy code. It's all about how to find seams in programs in order to isolate specific pieces for testing.Here's my solution to setting up the Inintial Context for my unit tests. First I added the following test dependency to my project:
Then I created a static method with the following code:
Finally in each of my test class I add an @BeforeClass method which calls setupInitialContext.
Today I've faced the same problem (we can't user PowerMock) and solved it this way:
Don't lookup in the constructor so when you invoke @InitMock on the object, the constructor doesn't require the context yet.
Create a method for retrieving the service bean when needed like "getService().serviceMethod(param, param ...)":
Have you considered mockito?
It's as easy as:
By the way, should you choose to use mocks i would recommend reading this article as well: http://martinfowler.com/articles/mocksArentStubs.html