Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[aspectj-users] AspectJ around singleton for testing

I'm looking at doing some system testing and mocking out (simulating responses from) other systems.  The problem is that many of the points of control to the system that I want to mock out are at library object calls that are implemented as singletons.  For example, I'd like to mock out the postTo call, and also avoid the setup code done by the private constructor:
 
        response = OurHttpClient.getInstance().postTo(url, msg);
 
Where OurHttpClient code is in a library jar file like this:
 
public class OurHttpClient {
        private static OurHttpClient instance;
        private OurHttpClient() { /* do some setup things that I don't want to run during my system testing */ }
        public static OurHttpClient getInstance() { if (instance == null) { instance = new OurHttpClient(); } return instance; }
        public String postTo(String url, String msg) { /* does post and returns response */ }
}
 
Again, I want to put in a mock so that when the postTo is called, I can return my canned response, simulating the system's indirect input. I also don't want some of the things that the private constructor does in the class to happen.  (This is a simple example, but I have other singletons that access JNDI for datasources and JMS queues and I want to run this outside the EJB container too). 
 
I first thought about putting an around advice for the getInstance() method.  The problem is that the next thing to execute after that would be the postTo(..) method on an OurHttpClient object instance, and because of how the singleton is written, I can't return an instance of OurHttpClient without going through the setup code inside the constructor.
 
Initially I opted for a non AOP solution, powerMockito.  I planned on replacing the getInstance() call to OurHttpClient with one that returned MyHttpClientMock.  But, as I described, the problem was that the next call needed an object of type OurHttpClient when it calls the postTo method.  So I made MyHttpClientMock a subclass of OurHttpClient thinking that I'd have an instance with which to call the postTo method that I could override:
 
public class MyHttpClientMock extends OurHttpClient {
        public static MyHttpClientMock getInstance() { return new MyHttpClientMock(); }
        public String postTo(String url, String msg) { /* returns simulated response */ }
}
 
The problem with this is that eclipse complains about not being able to call the OurHttpClient() constructor.  Now what?
 
Does aspectJ allow me to add another constructor to OurHttpClient, change the getInstance to point to it, so I can then mock out postTo() like I wanted to in the first place?
 
public class OurHttpClient {
        private static OurHttpClient instance;
/* woven in via aspectj: */
private OurHttpClient(String dummy) {  }
 
        private OurHttpClient() { /* do some setup things that I don't want to run during my system testing */ }
        public static OurHttpClient getInstance() {
                if (instance == null) {
                        instance = new OurHttpClient(); // AOP CHANGES THIS TO new OurHttpClient("dummy");
                }
                return instance;
        }
        public String postTo(String url, String msg) { /* does post and returns response */ }
}
 
As it turned out, in some of the cases I'm coding, the class I wanted to mock out actually called 'new' on another class, and I was able to join my code at that point, but I just got lucky that the 'new' call was done in the constructor before any of the setup code I didn't want to run happened.
 
When I consider using aspectj instead of powermockito to mock out the call, I still need to make sure the class's private constructor doesn't really get called.  I want to do an around advise of the getInstance, but I think I'm going to run into the same problem of requiring the around advise to return an object of type OurHttpClient so that the call to .postTo() is correct.  I don’t think I can give it just any object that implements postTo instead - it has to be one of type OurHttpClient, no? 
 
So here's my question.  I'd like to avoid the whole line being called.  Is there a simple way to do an around advise that goes around both calls at once?  Ie. Around an entire _expression_:  OurHttpClient.getInstance().postTo(..)? 
 
I'm trying to setup regression testing before refactoring, and wanted to be able to test without changing the SUT code.
 
TIA,
 
Bill McDonald
William.J.McDonald@xxxxxxxxxxxxxx
480-456-8417 office
CSTS (Consumer Credit Services and Technology Solutions)
 
This message may contain confidential and/or privileged information. If you are not authorized to receive this message, you must not take any action on this message. If you have received this message in error, please advise the sender immediately by reply e-mail and delete this message. Thank you for your cooperation.
 
 

Back to the top