Proxying static APIs to make code testable in Java - java

Here is the problem:
I am migrating a big legacy application in Java and I need to make some use of a certain (rather big) amount of legacy APIs exposed as static methods. We can't just avoid using these methods for now and these are making the whole bunch of stuff such as requesting database and so on. Using such methods as they are makes my code quite difficult to test and I am wondering what pros and cons may be if I introduce some non-static proxies to these APIs?
Consider the following example:
package my.legacy.project.util;
class LegacyRulesUtil {
...
public static IBusinessRules getRules(IQuery query) { ... }
...
}
package my.new.project.service.proxy;
#Service
class LegacyRulesProxyService {
...
public IBusinessRules getRules(IQuery query) {
return LegacyRulesUtil.getRules(query);
}
...
}
package my.new.project.consumer;
#Component
class Consumer {
private final LegacyRulesProxyService legacyRulesProxy;
#Autowired
public Consumer(LegacyRulesProxyService legacyRulesProxy) {
this.legacyRulesProxy = legacyRulesProxy;
}
public void consume() {
...
legacyRulesProxy.getRules(query);
...
}
}
Or maybe you know some good alternatives for that?
My primary goal is to make code easily testable. While using proxies I can mock them off and make some assertions over the method calls or just return back some dummy data from them and assert the final results.

That is absolutely the right way... partially.
Ideally you do not simply proxy your existing "Utility"-classes but make real Domain Objects. Those initially delegate to the statics but you can implement them the "new way" step by step.
That is, I would prefere a kind of facade pattern instead of the suggested proxy pattern.

PowerMockito can be used for mocking the static methods in your code. Instead of you creating proxies it would be done for you.
PowerMockito mock single static method and return object

Related

How to use guice injection for an existing singleton class?

I have an existing class named Legacy which is mostly written in old school singleton pattern. Now I want to introduce a new field to it and I would like to use Guice. Legacy itself is not Guice controlled, it is used by another Service class (inside the Service class, it calls the getInstance() of Legacy class to retrieve the Legacy object right now), and that Service class is been created using Guice injector.
public class Legacy {
public synchronized static Legacy getInstance() {
if(sInstance == null) {
sInstance = new Legacy();
}
return sInstance;
}
private Legacy() {
legacyObj = LegacyField.getInstance(); // get a singleton
}
private static Legacy sInstance;
private LegacyField legacyObj;
private NewField newObj; // this is the new dependency I would like to add using Guice
}
What I tried is that I tried to put method Inject into Legacy class
#Inject
public void setNewField(NewField newObj) {
this.newObj = newObj;
}
And in the module file of the Service, I bind the NewField object, but when I run the program, it throwed a NullPointer exception. So the inject doesn't work. Any idea of how to make NewField inject into my program but keep the current old-school singleton paradigm and not changing too much about everything else?
EDIT
There are a least three solutions below and I don't quite know which is the best or are they equivalent.
I just found another solution:
// put in the module
bind(Legacy.class).toInstance(Legacy.getInstance());
In this example, your module itself, not Guice, takes responsibility for obtaining a Legacy instance, then asks Guice to always use this single instance to fulfill all Legacy injection requests.
But according to the javadoc
When the Injector is created, it will automatically perform field and method injection for this instance, but any injectable constructor on Legacy is simply ignored. Note that using this approach results in "eager loading" behavior that you can't control.
Though only slightly cleaner than Thomas's answer, you can configure the injection of your Singleton from within your Module using requestInjection or requestStaticInjection.
// In your Module:
requestInjection(Legacy.getInstance()); // for an instance field, or
requestStaticInjection(Legacy.class); // for a static field.
The docs on the wiki warn about the downsides, though:
This API is not recommended for general use because it suffers many of the same problems as static factories: it's clumsy to test, it makes dependencies opaque, and it relies on global state.
Here is a somewhat hackish solution.
In the bootstrapping of your application,
may be in method public static void main(String[] args),
you should already have code similar to this:
Injector injector = Guice.createInjector(yourModule);
At this place add the following line:
injector.injectMembers(Legacy.getInstance());
By doing so, all the #Injects in your Legacy singleton
should be resolved.
See also the javadoc of Injector.injectMembers.

Is it possible to use JMockit's Deencapsulation API to exchange method implementation?

So, basically, a there is some poor code that I cannot change that needs to be tested. Traditionally, you inject your mocked dependencies, but with this code, I cannot do so, because there are no setter methods. Worse, the function I need to test calls a bunch of static factory methods-I can't just use the MockUp strategy to swap out the implementation there, because there is no class instance to be injected at all.
In C/++, you can retrieve a pointer to a function and know it's type by it's signature. If you changed the pointer, then you could potentially change how the stack was constructed by the compiler and you could pass function's around and all that Jazz.
Is there a way to use the Deencapsulation API to replace a static method implementation? Using this, I could write my own class, descend from the traditional, but return mocked objects in order that dependency injection still be achieved?
public class TestedClass {
public static void testedMethod() {
UnMockableType instanceVariable =
UnInjectableFactory.staticFactoryConstructor();
instanceVariable.preventControlFlowInfluenceThroughMocking();
}
}
Easy enough:
#Test
public void exampleTestUsingAMockUp()
{
new MockUp<UnMockableType>() {
#Mock
void preventControlFlowInfluenceThroughMocking() {}
};
TestedClass.testedMethod();
}
Above, UnInjectableFactory isn't mocked because it doesn't need to be (assuming it simply instantiates/recovers an UnMockableType).
It could also be done with #Mocked and the Expectations API.

how to elegantly dependency inject a primitive boolean for testing?

I'm using Mockito for unit testing, and as such, it looks like i'm able to inject certain objects using the #InjectMocks and #Mock annotations. I'm assuming i can do this for Object type Booleans
However, i can't seem to get this to work for primitive booleans. How do i do this? or what frameworks allow this? (i'm actually on an Android project)
for example:
class MethCook {
private Laboratory mLab; // i can inject this
private Assistant mJessePinkman; // this is injectable too
private boolean mCanCookPureCrystal; // how do i access/inject this?
private void cookBlueMeth() { ... }
private void onTraumatized() {
mCanCookPureCrystal = false;
startMoppingAround();
beDepressed();
neverWantToCookAgain();
}
}
note: elegance meaning brevity and conciseness, as in... i would prefer not to use #VisibleForTesting on top of getter/setters to access this boolean; as that would expose state mutability to the outside world?
If there's Inversion of Control, (#Autowired/#Value/#Resource), reflection is easy enough.
#Before
public void init() {
Field f = myMethCooking.getClass().getDeclaredField("mCanCookPureCrystal");
f.setAccessible(true);
f.set(myMethCooking, false);
}
java-set-field-value-with-reflection!
Mockito is a mocking framework, not an injection framework. The #Mock annotation does not support mocking things the developer doesn't own, like boolean.class.
Try setting the boolean in JUnit's #Before annotation, something like:
#Before public void inject_mCanCookPureCrystal() {
myMethCooking.setMCanCookPureCrystal(false);
}
Here is an issue in Mockito's enhancement request database that talks about extending annotations, possibly in a way that can be used with primitives: Mockito Issue 290.
If there is no setter for the value, then you'll want to execute a method that sets it as needed beforehand. Many testers will argue that if something can't be directly set externally, it's not part of the class's public contract and should not be set by injection, reflection, annotations or anything else, anyway. (See https://stackoverflow.com/a/2811171/325452 .)

Best Practice: Testing Interface Contract Compliance?

Assume that interface for is defined
interface Foo {
int getBaz();
void doBar();
}
Further assume that the contract states that everytime doBar is called baz is incremented. (Ok this is a contrived bit of code but stick with me here)
Now I want to provide a unit test that I can provide to Foo implementers so that they can verify that they meet all the contract conditions.
class FooTest {
protected Foo fooImpl;
#Test
public void int testBazIncrement()
{
int b = fooImpl getBaz();
fooImpl.doBar();
Assert.assertEquals( b+1, fooImpl.getBaz();
}
}
What are the best practices for making the test available to the implemnters of Foo? It seems to me that there needs to be a mechanism for them to call the FooTest and provide a Foo or a FooFactory to construct Foo instances. Furthermore, if there are many tests (think big interface) then I want to put all those tests in one FooTest class.
Are there any best practices for how to implement such tests?
This is a textbook example of Dependency Injection. If you use Spring as the DI container, you can wire in the fooImpl
#Inject
protected Foo fooImpl;
Your test needs to be annotated with #RunWith(SpringJUnit4ClassRunner.class), and it's up to the interface provider to configure Spring with their implementation.
Without a DI container, you can just create an abstract test class with all the tests in it and an abstract method to provide the implementation object.
protected abstract Foo createFoo();
It's up to the implementation provider to subclass the test and implement the abstract method.
class FooImplTest extends FooTestSuper {
#Override
protected Foo createFoo() {
return new FooImpl();
}
If you have multiple tests, consider JUnit's #Suite annotation. It's compatible with the Spring test runner.
You can implement a testDataFactory where you istance your objects, or use GSon for create your objects (personally, I like GSon, is clear and fast, you learn it in a few time).
For the test implementation, I suggest to write more tests and not a single one.
In this way, unit test can be indipendent and you can segregate your problems in a closed structure.
Sonar
Sonar is a tool that help you a lot, making analisys of your code. You can see from sonar front-end how you application is tested:
sonar unit test
as you can see, Sonar can show you where your code is tested or not
Why not just have, say, a InterfaceTester that gets called from the unit tests InterfaceImplATest, InterfaceImplBTest, etc?
e.g.
#Test
public void testSerialisation()
{
MyObject a = new MyObject();
...
serialisationTester.testSimpleRoundTrip(a);
serialisationTester.testEdgeCases(a);
...
}
After much pondering and some dead-ends I have begun using the following pattern:
In the following:
[INTERFACE] refers to the interface being tested.
[CLASS] refers to the implementation of the interface being tested.
Interface tests are built so that developers may test that implementations meet the contract
set out in the interface and accompanying documentation.
The major items under test use an instance of an [INTERFACE]ProducerInterface to create the instance of the object being tested. An implementation of [INTERFACE]ProducerInterface must track all the instances created during the test and close all of them when requested. There is an Abstract[INTERFACE]Producer that handles most of that functionality but requires a createNewINTERFACE implementation.
TESTS
Interface tests are noted as Abstract[INTERFACE]Test. Tests generally extend the Abstract[INTERFACE]ProducerUser class. This class handles cleaning up all the graphs at the end of the tests and provides a hook for implementers to plug in their [INTERFACE]ProducerInterface implementation.
In general to implement a test requires a few lines of code as is noted in the example below
where the new Foo graph implementation is being tested.
public class FooGraphTest extends AbstractGraphTest {
// the graph producer to use while running
GraphProducerInterface graphProducer = new FooGraphTest.GraphProducer();
#Override
protected GraphProducerInterface getGraphProducer() {
return graphProducer;
}
// the implementation of the graph producer.
public static class GraphProducer extends AbstractGraphProducer {
#Override
protected Graph createNewGraph() {
return new FooGraph();
}
}
}
SUITES
Test suites are named as Abstract[INTERFACE]Suite. Suites contain several tests that excersize all of the tests for components of the object under test. For example if the Foo.getBar() returned an instance of the Bar interface the Foo suite includes tests for the Foo iteself as well as running the Bar tests the Bar. Running the suites is a bit more complicated then running the tests.
Suites are created using the JUnit 4 #RunWith(Suite.class) and #Suite.SuiteClasses({ })
annotations. This has several effects that the developer should know about:
The suite class does not get instantiated during the run.
The test class names must be known at coding time (not run time) as they are listed in the annotation.
Configuration of the tests has to occur during the static initialization phase of class loading.
To meet these requirements the Abstract[INTERFACE]Suite has a static variable that holds the instance of the [INTERFACE]ProducerInterface and a number of local static implementations of the Abstract tests that implement the "get[INTERFACE]Producer()" method by returning the static instance. The names of the local tests are then used in the #Suite.SuiteClasses annotation. This makes creating an instance of the Abstract[INTERFACE]Suite for an [INTERFACE] implementation fairly simple as is noted below.
public class FooGraphSuite extends AbstractGraphSuite {
#BeforeClass
public static void beforeClass() {
setGraphProducer(new GraphProducer());
}
public static class GraphProducer extends AbstractGraphProducer {
#Override
protected Graph createNewGraph() {
return new FooGraph();
}
}
}
Note that the beforeClass() method is annotated with #BeforeClass. the #BeforeClass causes it to be run once before any of the test methods in the class. This will set the static
instance of the graph producer before the suite is run so that it is provided to the enclosed tests.
FUTURE
I expect that further simplification and removal duplicate code can be achieved through the use of java generics, but I have not gotten to that point yet.
Here are some of my thoughts about how to make a qualified unit test:
First of all, try to make your a implementer class fully tested, which means all of its methods should be covered by the UT. Doing this will save you a lot of time when you need to refactor your code. For your case, it could be :
class FooTest {
protected Foo fooImpl;
#Test
public void testGetBaz() {
...
}
#Test
public void testDoBar() {
...
}
}
You will find you need to check the internal state of your class and there is nothing wrong it for UT should be a kind of white-box test.
Second, all methods should be tested separately and not depend on each other. In my opinion, for your code posted above, it looks like more than a function test or an integration test, but it's also necessary.
Third, I don't think it's a good practice to use spring or other container to assemble the target object for you, which will make your test running relatively slow, especially when there a load of tests to run. And your class should intrinsically be pojo and you can complete the assembling in another method in your test class if your target object is really complex.
Fourth, if the parent interface of some class is really big, Dividing the test methods into several groups is something you should do. Here is more info.

What are ways to test methods that depend on static methods?

I need to test some security related classes that depend on Spring Security. This code makes use of SecurityContextHolder.getContext() which is static. How can I test the calling method without setting up an entire security context?
We are using JUnit 4 with Mockito. Mockito was pretty explicit in it's FAQ that static methods where not supported. Is there an alternative? An answer for the Spring Security case would be nice, but I am looking for a solution to the more general problem.
Have a look at PowerMock it will allow you to mock out static method, constructors and do all sorts of other crazy things you wouldn't normally be able to do with java. It integrates with most mocking libraries including mockito (look here http://code.google.com/p/powermock/wiki/MockitoUsage13 for an example).
In general I've found this to be a very useful library to have in your testing toolbox (when coding java). The only caveat is that since this library plays around with your bytecode, if you have other libraries that do bytecode instrumentation/manipulation you can run into trouble, but you won't know until you try.
You can refer to the following issue and inject org.springframework.security.core.context.SecurityContextHolderStrategy instance which functionality is available since Spring Security 3.0.
You should be able to simply call SecurityContextHolder.setContext() with a mocked SecurityContext in your setupt code. SecurityContextHolder just seems to be a thin wrapper around a ThreadLocal, so it should work fine.
Maybe refactoring code so it accepts some interface instead of getContext()? You'll need impl which will delegate all work to context, though.
UPDATE: Code will look like
interface SecurityContext {
void foo();
}
class SpringSecurityContext implements SecurityContext {
public void foo() {
// call spring static method here
}
}
class TestSecurityContext implements SecurityContext {
public void foo() {
// test case logic here
}
}
class SecurityContextClient {
private final SecurityContext context;
public SecurityContextClient(SecurityContext context) {
this.context = context;
}
void useSecurity() {
context.foo();
}
}

Categories

Resources