how to elegantly dependency inject a primitive boolean for testing? - java

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

Related

Proxying static APIs to make code testable in 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

Guice / DI and mixing injection and parameters passed in at runtime

I have a situation where when I initialize some of my classes, some of the fields I need to be injected (e.g. references to factories etc) whereas some others are dynamic and created at runtime (e.g. usernames etc). How do I construct such objects using the GUICE framework?
Simply annotating the fields I need injected as #Inject doesn't work as they seem to not be set up when creating an object using the constructor. For instance:
class C {
#Inject
private FactoryClass toBeInjected;
private ConfigurationField passedIn;
public C(ConfigurationField passedIn) {
this.passedIn = passedIn;
}
}
If my understanding is correct (and I could be wrong), the fact that I'm creating a new instance of C via new and not through Guice means that no injection will take place. I do need to pass these parameters in the constructor, but also want some fields injected -- so how do I solve this problem?
A feature specifically matching "mixing injection and parameters passed" would be Assisted Injection.
class C {
// Guice will automatically create an implementation of this interface.
// This can be defined anywhere, but I like putting it in the class itself.
interface Factory {
C create(ConfigurationField passedIn);
}
#Inject
private FactoryClass toBeInjected;
private ConfigurationField passedIn;
private SomeOtherDepIfYoudLike otherDep;
#Inject public C(#Assisted ConfigurationField passedIn,
SomeOtherDepIfYoudLike otherDep) {
this.passedIn = passedIn;
this.otherDep = otherDep;
}
}
Now in your module:
#Override public void configure() {
install(new FactoryModuleBuilder().build(C.Factory.class));
}
Now when someone wants to create a C, they can avoid calling the constructor directly; instead, they inject a C.Factory into which they pass a ConfigurationField instance of their choice and receive a fully-constructed, fully-injected C instance. (Like with most well-designed DI objects, they can call the constructor directly.)
Note that this design is especially useful in a few ways:
You can use constructor injection, treat all your fields as final, and treat the object as immutable.
If you stick with constructor injection entirely, your object will never be in a partially-initialized state, and your API stays simple (call the constructor and your object is ready).
For testing, you can write any implementation of C.Factory and have it return any instance you want. This can include test doubles of C or its factory: Fakes, mocks, or spies that you create manually or by using Mockito, EasyMock, JMock, or any other mocking framework.
What you are looking for is "On Demand" Injections:
public static void main(String[] args)
{
Injector injector = Guice.createInjector(...);
CreditCardProcessor creditCardProcessor = new PayPalCreditCardProcessor();
injector.injectMembers(creditCardProcessor);
}
or for static things
#Override public void configure() {
requestStaticInjection(ProcessorFactory.class);
...
}
All explained very well https://github.com/google/guice/wiki/Injections#on-demand-injection.
Note:
Both of these things are code smells and should only really be used
for migrating old code over to Guice. New code should not use these
approaches.

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.

Why Cannot I use Mock and InjectMocks together?

valid construction:
#InjectMocks
SomeClass sc = mock(SomeClass.class);
Invalid construction:
#InjectMocks
#Mock
SomeClass sc;
I want to inject mocks to another mock. I want to use only annotation style.
Why was in Mockito forbid second construction ?
Update
example:
public class ArrTest {
private SomeClass someClass;
public List<String> foo(){
anotherMethod(); // I suppose that this method works. I want to test it separately.
//logic which I need to test
return someClass.doSmth();// I suppose that this method works. I want to test it separately.
}
public void anotherMethod(){
///...
}
}
public class SomeClass {
public List<String> doSmth(){
return null;
}
}
test:
public class ArrTestTest {
#InjectMocks
ArrTest arrTest = Mockito.mock(ArrTest.class);
#Mock
SomeClass someClass;
#Test
public void fooTest(){
Mockito.when(someClass.doSmth()).thenReturn(new ArrayList<String>());
Mockito.doNothing().when(arrTest).anotherMethod();
System.out.println(arrTest.foo());
}
}
It sounds like you're trying to do something that doesn't really make sense. You shouldn't need to inject any dependencies into your mock since mocks by definition don't have any behaviour until you define it with when(mock.someMethod()).thenAnswer() or some variation.
(except perhaps if you're using a spy(), but you've specifically said you're using a #Mock).
Maybe you could explain your use case and why you're trying to inject dependencies into a mock?
#InjectMocks specifically indicates that the annotated field will NOT contain a mock. Annotating #InjectMocks #Mock is not just unsupported—it's contradictory.
To return stubs wherever possible, use this:
#Mock(answer=Answers.RETURNS_DEEP_STUBS)
YourClass mockYourClassWithDeepStubs;
But heed the official documentation for this Answer:
WARNING: This feature should rarely be required for regular clean code! Leave it for legacy code. Mocking a mock to return a mock, to return a mock, (...), to return something meaningful hints at violation of Law of Demeter or mocking a value object (a well known anti-pattern).
Good quote I've seen one day on the web: every time a mock returns a mock a fairy dies.
A mock doesn't have any real implementation. #InjectMocks would try to find and call setters for whatever mock objects have already been created and pass them in. Mockito "knows" that this is kinda pointless on a mock, since there won't be any way to get the mock objects back out, much less do anything meaningful with them.

Unit testing JSR-330 injected objects

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.

Categories

Resources