Unit testing JSR-330 injected objects - java

I have previously used Spring DI, and one of the benefits I perceive is that I can test my Spring bean classes without involving Spring (imports omitted for brevity):
public class Foo {
private String field;
public void setField(String field) { this.field = field; }
public String getField() { return field; }
}
public class TestFoo {
#Test
public void test_field_is_set() {
Foo foo = new Foo();
foo.setField("Bar");
assertEquals("Bar", foo.getField());
}
}
Now I am experimenting with JSR-330, which means not explicitly writing setters.
I'm using Hk2 so far, purely because of some anecdotal stuff about Jersey being tied to Hk2, and making it difficult to co-habit with other JSR-330 implementations.
public class Foo {
#Inject
private String field;
}
I half expected some magic to happen, whereby the #Inject annotation caused a setter to become available, but this is not the case:
Foo foo = new Foo();
foo.setField("Bar"); // method setField(String) is undefined for the type Foo
How can I (conveniently) test this kind of annotated class without invoking a framework?
Failing that, how can I invoke a framework in a portable way (i.e. without tightly coupling my test code to Hk2, Guice, etc.)
Failing that, what's a typical, clean way to test classes annotated in this way?

Simplest is to make the fields package-private (instead of private), then in the test, set them directly. (That works if the test is in the same package)
public class Foo {
#Inject
String field;
}
Foo foo = new Foo();
foo.field = "bar";
This has the advantage of avoiding reflection so it's safe for refactoring.

The field injection approach you mentioned is actually the typical Spring style; many programmers don't write setters for private injected fields at all. Spring (with #Autowired or #Inject) and JSR-330 containers usually inject fields using direct field reflection rather than setters.
Because of this, if you don't want to use any DI framework, you could write the necessary reflection code into your unit tests yourself, but this seems like overkill just to avoid a test dependency; after all, the point of using #Inject is that you're coding to an interface, and you don't avoid using the JVM to avoid coupling to it.
The usual approach for testing this sort of class is to set up a test context for whatever container you prefer and run the unit tests in that context. If you're using Spring, you'd put an applicationContext-test.xml file or TestConfig class in your src/test/ directory (or equivalent), and if you're using Guice, you'd write a module to wire up mocks or test datasets.

It turns out that frameworks relying on private/protected field access are not so uncommon. Hibernate, JPA, several JSR-330 implementations, including Spring itself, all do it.
Spring's spring-test package provides a ReflectionTestUtils class containing static methods for accessing these fields.
Using this one can test the class in the question thus:
import static org.springframework.test.util.ReflectionTestUtils.*;
...
#Test
public void testUsingSpringReflectionTestUtils() {
Foo foo = new Foo();
setField(foo, "field", "Bar");
assertEquals("Bar", foo.getField());
}
You need spring-test and spring-core in your test classpath for this to work, but it doesn't add a dependency on Spring for your production code.
(Comments welcome about alternative implementations of the same principle welcome. I don't think it's worth rolling one's own, however simple it would be, given that Spring has a good implementation.)

Give "needle" a try: http://needle.spree.de/overview
needle is an DI-test-framework that only simulates the container behavior, making unit tests real simple.

Related

Internal working of field injection in spring and why is it not recommended to use

As the title suggests , I want to know how does field injection internally works in spring , I read many articles on this and got to know few things like below but didn't understood the exact reason behind it :
-> It should not be used because when you do unit testing then you are dependent upon the spring
container to instantiate the class in case of field injection.
-> You cannot use "final" keyword in case of field injection , means you cannot make the field immutable.
-> It internally uses reflection
I want to know how exactly does #Autowired works internally , how does it uses reflection , I am trying to understand the exact reason behind all the above mentioned points, what happens behind the scenes when we write the below code :
#Component
public class B {
#Autowired
private A a1;
}
I have read similar questions on stack overflow about this topic , but I couldn't find the exact explanation that I am looking.
Spring has a concept of Bean Post Processors.
When spring builds a bean it applies registered bean post processors that help to "initialize" the bean.
So, there is org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor that handles autowiring.
Basically it works with an newly created object. Spring introspects the fields of the beans (by using reflection). The fields that have #Autowired is a subject for processing with this bean post processor. It finds the candidate for injection in the application context and actually injects the value.
Now given this information, its understandable why final fields cannot be autowired. Leave alone spring, In pure Java, final fields must be instantiated directly right during the declaration (final int i = 123) or in the constructor of the class. But the autowiring happens after constructor, so its impossible to autowire the final fields.
As for the unit testing, the private properties must be somehow configured from the test. But since they're encapsulated (yes, spring kind of breaks encapsulation in this case for its usage), its impossible to write a good test for the class that contains fields injection. That's is a reason to switch to constructor injection.
public class FieldInjection {
#Autowired
private A a;
}
VS.
public class ConstructorInjection {
private final A a;
// this can be generated by lombok, you don't have to put #Autowired on constructor in the case of single constructor, spring will use it to create a bean
public ConstructorInjection(A a) {
this.a = a;
}
}
Now the test for FieldInjection class is impossible:
public class FieldInjectionTest {
#Test
void test() {
FieldInjection underTest = new FieldInjection();
how do you know that you should instantiate A a. ????
}
}
However in the case of constructor injection its a trivial task:
public class ConstructorInjectionTest {
#Test
void test() {
A a = mock(A.class);
ConstructorInjection underTest = new ConstructorInjection(a);
// the dependencies must be supplied in the constructor
// otherwise its impossible to create an object under test
}
}

How to mock a class created in constructor?

Imagine I have a bean JdbcTemplate, and in only once class I need NamedParameterJdbcTemplate explicit. It is created inside the constructor.
Question: how can I mock it during junit tests?
#Service
public class QueryService {
private final NamedParameterJdbcTemplate namedJdbc;
public BookingExportService(JdbcTemplate jdbc) {
this.namedJdbc = new NamedParameterJdbcTemplate(jdbc);
}
public void sql() {
namedJdbc.query(sql1, mapSqlParameterSource, resultSetExtractor);
namedJdbc.query(sql2, mapSqlParameterSource, resultSetExtractor);
}
}
Defining the mock is difficult here, as I have to mock the underlying JdbcTemplate calls. This could work as follows:
#MockBean
private JdbcTemplate jdbc;
#Test
public void testQuery() {
when(jdbc.query(any(PreparedStatementCreator.class), any(ResultSetExtractor.class))).thenReturn(..);
}
BUT: if I have different sql queries that should produce different results (like above sql1 and sql2), then I'm out of luck and cannot differ the sql during the mock.
What are my chances?
Here:
this.namedJdbc = new NamedParameterJdbcTemplate(jdbc);
That simply makes your code hard to test. Basically you are bypassing dependency injection here, and well, that means: you don't have any control over that field content.
Three options:
turn to a mocking framework like PowerMock(ito) or JMockit that allow you to control calls to new() (not recommended)
change your code, for example using constructor telescoping ... so that you can simply pass in an instance of that class (which can then be mocked with "normal" frameworks like Mockito easily)
as you are already using a framework that has its own ideas of dependency injection (#Autowired for example): step back and do things like that framework implies it to be done.

Injection via Guice into an Immutables class

I'm using 2 common packages, Immutables and
Guice. The very first thing that happens at runtime is I load setting from environment and other sources into settings into a singleton, non-Immutable config class, let's call it MyConfig, that for example, exposes a public getSettingX() method.
MyConfig myConfig = MyConfig.intialize().create();
String settingX = myConfig.getSettingX();
I have one abstract Immutable class, call it AbstractImmutable. that at instantiation needs to set a field based on the myConfig.getSettingX().
#Value.Immutable
abstract class AbstractImmutable {
abstract String getSettingX(); // Ideally set
}
Now, typically I inject MyConfig into classes using Guice, and would liket to figure a way to do this for implementations of the AbstractImmutable class (to avoid manually having to inject the MyConfig class every time I build an object--whole reason using juice to begin with, to manage my DI). However, since the concrete Immutables classes are generated at compile, it doesn't to work with the usual Guice injection annotations.
There's indication on the Immutables site of using the builder package to annotate a static factory method, but I can't seem to figure how to add this to the abstract immutable class.
Anyone have any suggestions?
To my knowledge, there is no way to do this on the generated Immutables class itself (though there may be some funny stuff you could do with #InjectAnnotation), so you may be out of luck there.
Even though you are asking under the guise of Guice, what you are asking for reminds me of the pattern that AutoFactory uses, and should be similarly applicable. In essence, take advantage of the Factory Pattern by injecting into the factory and then the factory will create the Immutable object.
For example, specifically referring to your case,
#Value.Immutable
abstract class ValueObject {
MyConfig getMyConfig();
#Value.Derived
String getSettingX() {
getMyConfig().getSettingX();
}
String getAnotherProperty();
class ValueObjectFactory {
#Inject MyConfig myConfig;
ValueObject create(String anotherProperty) {
return ImmutableValueObject.builder()
.setMyConfig(this.myConfig)
.setAnotherProperty(anotherProperty)
.build();
}
}
}
Then, in the application code, you would inject the ValueObjectFactory directly and call create on it as
class SomeApplicationClass {
#Inject ValueObjectFactory factory;
void someMethod() {
ValueObject = factory.create("myString");
// ... do something with the ValueObject
}
}
Similarly, you could define your factory as a builder, but that will be a decision you will have to make based on the number of parameters you have.

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 .)

How to test/mock this static factory (used for graph construction)?

So, I have implemented my business classes, where I pass in all dependencies via the constructor, so I can mock those out and easily unit test them. This works great so far, but then, at one point, I need to create an object graph out of those objects. For this, I'm using a static factory (I can't use a DI framework, sadly). Example:
public class FooBar {
public FooBar(Foo foo, Bar bar) {
this.foo = foo;
this.bar = bar;
}
}
public class Foo {
public Foo() {}
}
public class Bar {
public Bar(Foo foo) {
this.foo = foo;
}
}
public class GraphFactory {
public static FooBar newFooBar() {
Foo foo = new Foo();
Bar bar = new Bar(foo);
return new FooBar(foo, bar);
}
}
So, I'm not able to really test the GraphFactory (can't mock the dependencies), which is kinda ok (not much work is done here). But what if construction of the graph is more complex, i.e. it involves looking up some properties, doing JNDI lookups and so on?
Should I still not write a unit test for this? Is my class design maybe broken? Isn't the purpose of unit testing to test classes in isolation?
There is nothing wrong with this design and it is fully testable. If we focus on the single responsibilty of the factory -- it is responsible for assembling the object graph -- the tests for this are straight forward:
Set up the factory with its prerequisites.
Invoke the factory method.
Assert that the object was constructed to your requirements: default values are set, etc.
In the example above, foo, bar, and foobar are the result of the test and do not need to be mocked.
If the assembly of the object graph is more complex, and you need additional services to fetch data and check application settings, guess what happens? These dependencies are passed into the factory through its constructor. You should mock these dependencies to isolate the factory from its dependencies' dependencies. Consumers of your factory would receive a fully wired factory through their constructor; or the factory is assembled at application start-up and made available as a singleton, etc.
This is how DI works. It sounds peculiar because now you have to worry how the factory is created (and who created that object,etc, turtles all the way down) and this is a perfectly natural reaction.
That's why we have DI frameworks to assemble complex object graphs. In a well designed DI application, nothing should know how the graph was assembled. Akin to this design, nothing should know about the DI framework.
The only exception to that rule, is... (drum-roll)... a factory object!
Most DI frameworks will inject the DI container into an object if the object being resolved takes a DI in it's constructor. This greatly simplifies the factory's plumbing, and satisfies our design principles: no one knows how to construct our object except our factory and we've encapsulated knowledge of the DI container to key areas of the application that are responsible for object assembly.
Whew. Now, if you're still following along, how does this change our test? It shouldn't, at least not too much: step #1 changes slightly, where you fill the DI container with mock objects, and then construct the factory with the DI container.
As a matter of taste, some like to use auto-mocking DI containers during testing that will automatically generate mock dependencies when an item is requested. This can remove most of the set up pain.
If the newFooBar method had to be more complex, you could refactor out everything except for the creation of the Foo and the Bar into a package-private initialisation method. Then write tests for the initialisation method.
public class GraphFactory {
public static FooBar newFooBar() {
Foo foo = new Foo();
Bar bar = new Bar(foo);
FooBar toReturn = new FooBar(foo, bar);
initialise( toReturn );
return toReturn;
}
static void initialise( FooBar toInitialise ){
// some stuff here that you can test
}
}
You can't mock or stub static method calls but you can write a unit test for the factory without mocks.
But, why do you use static factory methods?. May be better to store the factory in a static variable if you want to access it in a static way.
You should give a look into Dependecy Injection, which will allow you get rid of the factory when used properly. I recommend you this video as an introduction, it helped me a lot:
http://code.google.com/p/google-guice/
It's an introduction to Guice, a library from google, but it will help you understand DI. Then you'll see how to replace all those 'new' with annotations, letting the library do all the work for you. Some people would recommend Sring instead, but i find Guice more friendly for beginners. I just hope this doesn't fire a Guice vs Spring discussion again :D

Categories

Resources