Getting around setter injection using mockito's #InjectMocks - java

I have an abstract class with two Map fields. One I would like to mock and inject into an object of a subclass of AbstractClass for unit testing. The other I really don't care much about, but it has a setter.
public abstract class AbstractClass {
private Map<String, Object> mapToMock;
private Map<String, Object> dontMockMe;
private void setDontMockMe(Map<String, Object> map) {
dontMockMe = map;
}
}
When using #InjectMocks, it automatically tries to inject in the order: constructor, setter, field. It checks if it can inject in each of these places by checking types, then names if there are multiple type possibilities. This doesn't work well for me, because my mocked mapToMock is actually injected into dontMockMe via its setter. I cannot edit this abstract class. Is there any way for me to get around the setter injection? Thank you in advance!

Well this is a corner case, where automatic injection won't work in the way Mockito injection is currently designed. Also Mockito suffer from some shortcomings when there is multiple fields with the same types.
So to understand why this doesn't work let's dive a bit in the way Mockito performs injection :
It will try to inject dependencies via constructor injection, if it successes it won't try the following steps in order to protect the newly created instance from eventual side effects.
Then if constructor injection did not happen (no arg constructor, or object already instantiated), then Mockito will look for matches between mocks and setters. But it has to make some choices for it to happen automatically.
If there is only mock of type A and only one setter with type A then setter injection will happen.
If there is either multiple mocks or setters of type A it will try to find match using the type and the name of the mock (usually the #Mock field name). If matches are found then injection will happen.
Then if there is still some mocks left for injection, field injection might happen, using the same algorithm as with setter :
If there is only mock of type A and only one field with type A then field injection will happen.
If there is either multiple mocks or field of type A it will try to find match using the type and the name of the mock (usually the #Mock field name). If matches are found then injection will happen.
At the moment your code is stuck at stage 2.1 because there is probably only one mock available.
That being said with the current implementation of Mockito there is no real elegant solution, it is necessary to write yourself the injection code. And that is actually the wanted point with Mockito injection, if injection is too complex or weird, then you will have to write it out ; writing this boilerplate code is actually the best tool to question the current design.
Mockito injection is really designed for simple, straight designs.
In my opinion, I find wrong :
to mock a Map, a type you don't own, that might cause many problems.
to mock only a single map in tested object, that means your test knows too much about the inner working of the tested object.
It would benefit the design if you refactor the code and make the collaborators emerge. With clear dependencies/collaborators it will most certainly make the injection clearer too. Also the test should focus on asserting the interactions with the collaborators not how data how the implementation is done, data should only be tested as a result to a given input.

Related

Unit testing save methods when return type is void

Is there any way to write unit tests for save methods in DAO layer when return type is void? I'm using Log4j, Junit in spring boot project.
I've tried many ways to assert them. But since they aren't returning any value i wasn't able to assert them.
If the method is void, then it has side-effects, otherwise it would be a no-op.
So you call the method, then check if the desired side-effect happened.
E.g. setFoo(7) should mean that getFoo() returns 7, though unit testing simple getter/setter methods is a waste of time.
It is common to use mock objects to detect the side-effects, but it all depends on what the expected side-effect is. See: What is the purpose of mock objects?
There are several ways to unit test a method that returns void.
Change the method so that it returns a value even though you don't use that value. This is NOT the best way, but I note it here for completeness.
The method likely changes the state of the object in some way. A file was saved, a value was stored somewhere, parameters have been changed, etc. So check the values that should have been changed. You can read back a saved file, a changed variable, data in a test database, etc.
Mock objects can be used to determine if a method was called and what the behavior was. There are a number of mock object frameworks for Java, including Easy Mock, JMockit and Mockito. How to use a mock framework is beyond the scope of this answer, but I did include links to the various sites for your reference.
If bad inputs are given to the method it may throw an exception. It is a good idea to do this to test the error handling of your methods.
According to your comments you need to write an unit test for a save method. Try this example code,
#Autowired
private EmployeeDAO employeeDAO;
#Test
public void whenValidEmployee_thenShouldSave()
{
EmployeeEntity employee = new EmployeeEntity("1", "Department Name", "Role"); //id, department name and role are passing as constructor parameters
employeeDAO.save(employee);
List<EmployeeEntity> employees = employeeDAO.findAll();
//Assert
Assert.assertEquals(employee.getId(), employees.get(0).getId());
}
Writing a testable code is important as a developer in modern days. You should understand that a method with void, is bad for a single reason.it is not testable by any means. i would suggest you below actions to take
Improve your code with a relevant return type.
It's worth applying DbUnit, rather than applying just Junit to test
your DAO layer.
#Teguwih

Dependency injection on a protected field using #Inject [duplicate]

I read in some posts about Spring MVC and Portlets that field injection is not recommended. As I understand it, field injection is when you inject a Bean with #Autowired like this:
#Component
public class MyComponent {
#Autowired
private Cart cart;
}
During my research I also read about constructor injection:
#Component
public class MyComponent {
private final Cart cart;
#Autowired
public MyComponent(Cart cart){
this.cart = cart;
}
}
What are the advantages and the disadvantages of both of these types of injections?
EDIT 1: As this question is marked as duplicate of this question i checked it. Cause there aren't any code examples neither in the question nor in the answers it's not clear to me if i'm correct with my guess which injection type i'm using.
Injection types
There are three options for how dependencies can be injected into a bean:
Through a constructor
Through setters or other methods
Through reflection, directly into fields
You are using option 3. That is what is happening when you use #Autowired directly on your field.
Injection guidelines
A general guideline, which is recommended by Spring (see the sections on Constructor-based DI or Setter-based DI) is the following:
For mandatory dependencies or when aiming for immutability, use constructor injection
For optional or changeable dependencies, use setter injection
Avoid field injection in most cases
Field injection drawbacks
The reasons why field injection is frowned upon are as follows:
You cannot create immutable objects, as you can with constructor injection
Your classes have tight coupling with your DI container and cannot be used outside of it
Your classes cannot be instantiated (for example in unit tests) without reflection. You need the DI container to instantiate them, which makes your tests more like integration tests
Your real dependencies are hidden from the outside and are not reflected in your interface (either constructors or methods)
It is really easy to have like ten dependencies. If you were using constructor injection, you would have a constructor with ten arguments, which would signal that something is fishy. But you can add injected fields using field injection indefinitely. Having too many dependencies is a red flag that the class usually does more than one thing, and that it may violate the Single Responsibility Principle.
Conclusion
Depending on your needs, you should primarily use constructor injection or some mix of constructor and setter injection. Field injection has many drawbacks and should be avoided. The only advantage of field injection is that it is more convenient to write, which does not outweigh all the cons.
Further reading
I wrote a blog article about why field injection is usually not recommended: Field Dependency Injection Considered Harmful.
This is one of the never-ending discussions in software development, but major influencers in the industry are getting more opinionated about the topic and started to suggest constructor injection as the better option.
Constructor injection
Pros:
Better testability. You do not need any mocking library or a Spring context in unit tests. You can create an object that you want to test with the new keyword. Such tests are always faster because they do not rely on the reflection mechanism. (This question was asked 30 minutes later. If the author had used constructor injection it would not have appeared).
Immutability. Once the dependencies are set they cannot be changed.
Safer code. After execution of a constructor your object is ready to use as you can validate anything that was passed as a parameter. The object can be either ready or not, there is no state in-between. With field injection you introduce an intermediate step when the object is fragile.
Cleaner expression of mandatory dependencies. Field injection is ambiguous in this matter.
Makes developers think about the design. dit wrote about a constructor with 8 parameters, which actually is the sign of a bad design and the God object anti-pattern. It does not matter whether a class has 8 dependencies in its constructor or in fields, it is always wrong. People are more reluctant to add more dependencies to a constructor than via fields. It works as a signal to your brain that you should stop for a while and think about your code structure.
Cons:
More code (but modern IDEs alleviate the pain).
Basically, the field injection is the opposite.
Matter of taste. It is your decision.
But I can explain, why I never use constructor injection.
I don't want to implement a constructor for all my #Service, #Repository and #Controller beans. I mean, there are about 40-50 beans or more. Every time if I add a new field I would have to extend the constructor. No. I don't want it and I don't have to.
What if your Bean (Service or Controller) requires a lot of other beans to be injected? A constructor with 4+ parameters is very ugly.
If I'm using CDI, constructor does not concern me.
EDIT #1:
Vojtech Ruzicka said:
class has too many dependencies and is probably violating single
responsibility principle and should be refactored
Yes. Theory and reality.
Here is en example: DashboardController mapped to single path *:8080/dashboard.
My DashboardController collects a lot of informations from other services to display them in a dashboard / system overview page. I need this single controller. So I have to secure only this one path (basic auth or user role filter).
EDIT #2:
Since everyone is focused on the 8 parameters in the constructor... This was a real-world example - an customers legacy code. I've changed that. The same argumentation applies to me for 4+ parameters.
It's all about code injection, not instance construction.
One more comment - Vojtech Ruzicka stated that Spring injects beans in such three ways (the answer with the biggest numbers of points) :
Through a constructor
Through setters or other methods
Through reflection, directly into fields
This answer is WRONG - because FOR EVERY KIND OF INJECTION SPRING USES REFLECTION!
Use IDE, set breakpoint on setter / constructor, and check.
This can be a matter of taste but it can also be a matter of a CASE.
#dieter provided an excellent case when field injection is better. If You're using field injection in integration tests that are setting up Spring context - the argument with testability of the class is also invalid - unless You want to write later on tests to Your integration tests ;)

Can you #InjectMock deep stubs without defining a #Mock field?

Can you have mocks injected into an #InjectMock be deep stubs or do you need to define each mock with deep stubs? It's inconvenient to define an unused field only for the purpose of annotating it with deep stubs.
Example, is there a way to do this without defining injected, since it's never used anywhere?
#InjectMocks
private Object testMe;
#Mock (answer = Answers.RETURNS_DEEP_STUBS)
private Object injected;
No, you can't. You're also stacking up a fun assortment of warning labels:
From RETURNS_DEEP_STUBS:
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.
From #InjectMocks:
Mockito will try to inject mocks only either by constructor injection, setter injection, or property injection in order and as described below. If any of the following strategy fail, then Mockito won't report failure; i.e. you will have to provide dependencies yourself.
Constructor injection; the biggest constructor is chosen, then arguments are resolved with mocks declared in the test only. If the object is successfully created with the constructor, then Mockito won't try the other strategies. Mockito has decided to no [sic] corrupt an object if it has a parametered constructor.
By allowing InjectMocks with automatic deep stubs, you may find it very hard to reason about which injection style and field population you actually use, and which parts of your test are real versus mocked. This would also prevent you from stubbing or verifying any values other than by getting them directly through your system-under-test, which may incur side effects or otherwise break the boundary between real code and test code.
In short, the answer is "no"; the longer answer is that you should consider refactoring to include proper dependency-injection access and avoid any current Law of Demeter violations.

Why use constructor over setter injection in CDI?

I couldn't find any reasonable answer here on SO so I hope it's not a duplicate. So why should I prefer setter or constructor injection over simple
#Inject
MyBean bean;
I get the usage of the constructor injection if you need to do something with injected bean during your class initialization like
public void MyBean(#Inject OtherBean bean) {
doSomeInit(bean);
//I don't need to use #PostConstruct now
}
but still, it's almost the same like #PostConstruct method and I don't get setter injection at all, isn't it just a relic after Spring and other DI frameworks?
Constructor and property injection gives you the option to initialize the object even in a non CDI environment easily, e.g a unit test.
In a non-CDI environment you can still simply use the object by just passing the constructor arg.
OtherBean b = ....;
new MyBean(b);
If you just use field injection you usually must use reflection to access the field, because fields are usually private.
If you use property injection you can also write code in the setter. E.g. validation code or you clear internal caches that hold values which are derived from the property that the setter modifies. What you want to do depends on your implementation needs.
Setter vs constructor injection
In object-oriented programming an object must be in a valid state after construction and every method invocation changes the state to another valid state.
For setter injection this means that you might require a more complex state handling, because an object should be in a valid state after construction, even if the setter has not been invoked yet. Thus the object must be in a valid state even if the property is not set. E.g. by using a default value or a null object.
If you have a dependency between the object's existence and the property, the property should either be a constructor argument. This will also make the code more clean, because if you use a constructor parameter you document that the dependency is necessary.
So instead of writing a class like this
public class CustomerDaoImpl implements CustomerDao {
private DataSource dataSource;
public Customer findById(String id){
checkDataSource();
Connection con = dataSource.getConnection();
...
return customer;
}
private void checkDataSource(){
if(this.dataSource == null){
throw new IllegalStateException("dataSource is not set");
}
}
public void setDataSource(DataSource dataSource){
this.dataSource = dataSource;
}
}
you should either use constructor injection
public class CustomerDaoImpl implements CustomerDao {
private DataSource dataSource;
public CustomerDaoImpl(DataSource dataSource){
if(dataSource == null){
throw new IllegalArgumentException("Parameter dataSource must not be null");
}
this.dataSource = dataSource;
}
public Customer findById(String id) {
Customer customer = null;
// We can be sure that the dataSource is not null
Connection con = dataSource.getConnection();
...
return customer;
}
}
My conclusion
Use properties for every optional dependency.
Use constructor args for every mandatory dependency.
PS: My blog The difference between pojos and java beans explains my conclusion in more detail.
EDIT
Spring also suggests to use constructor injection as I found in the spring documentation, section Setter-based Dependency Injection.
The Spring team generally advocates constructor injection, as it lets you implement application components as immutable objects and ensures that required dependencies are not null. Furthermore, constructor-injected components are always returned to the client (calling) code in a fully initialized state. As a side note, a large number of constructor arguments is a bad code smell, implying that the class likely has too many responsibilities and should be refactored to better address proper separation of concerns.
Setter injection should primarily only be used for optional dependencies that can be assigned reasonable default values within the class. Otherwise, not-null checks must be performed everywhere the code uses the dependency. One benefit of setter injection is that setter methods make objects of that class amenable to reconfiguration or re-injection later. Management through JMX MBeans is therefore a compelling use case for setter injection.
Constructor injection is also a better way when you think about unit tests, because it is easier to call the constructor instead of setting private (#Autowired) fields.
When using CDI, there is no reason whatsoever to use constructor or setter injection. As noted in the question, you add a #PostConstruct method for what would otherwise be done in a constructor.
Others may say that you need to use Reflection to inject fields in unit tests, but that is not the case; mocking libraries and other testing tools do that for you.
Finally, constructor injection allows fields to be final, but this isn't really a disadvantage of #Inject-annotated fields (which can't be final). The presence of the annotation, combined with the absence of any code explicitly setting the field, should make it clear it is to be set by the container (or testing tool) only. In practice, no one will be re-assigning an injected field.
Constructor and setter injection made sense in the past, when developers usually had to manually instantiate and inject dependencies into a tested object. Nowadays, technology has evolved and field injection is a much better option.
Accepted answer is great, however it doesn't give credit to the main advantage of constructor injection - class immutability, which helps to achieve thread-safety, state safety, and better readability on the classes.
Consider you have class with dependencies and all of those dependencies are provided as constructor arguments, then you can know that the object will never exist in a state where dependencies are invalid. There is no need for setters for those dependencies (as long as they are private), so the object is instantiated to a full state or is not instantiated at all.
An immutable object is much more likely to well behave in an multithreaded application. Although the class still needs to be made internally thread-safe, you don't have to worry about external clients coordinating access to the object.
Of course this can be usefull only in certain scenarios. Setter injection is great for partial depencdency, where for example we have 3 properties in a class and 3 arg constructor and setters methods. In such case, if you want to pass information for only one property, it is possible by setter method only. Very useful for testing purposes.

How to mock object construction?

Is there a way to mock object construction using JMock in Java?
For example, if I have a method as such:
public Object createObject(String objectType) {
if(objectType.equals("Integer") {
return new Integer();
} else if (objectType.equals("String") {
return new String();
}
}
...is there a way to mock out the expectation of the object construction in a test method?
I'd like to be able to place expectations that certain constructors are being called, rather than having an extra bit of code to check the type (as it won't always be as convoluted and simple as my example).
So instead of:
assertTrue(a.createObject() instanceof Integer);
I could have an expectation of the certain constructor being called. Just to make it a bit cleaner, and express what is actually being tested in a more readable way.
Please excuse the simple example, the actual problem I'm working on is a bit more complicated, but having the expectation would simplify it.
For a bit more background:
I have a simple factory method, which creates wrapper objects. The objects being wrapped can require parameters which are difficult to obtain in a test class (it's pre-existing code), so it is difficult to construct them.
Perhaps closer to what I'm actually looking for is: is there a way to mock an entire class (using CGLib) in one fell swoop, without specifying every method to stub out?
So the mock is being wrapped in a constructor, so obviously methods can be called on it, is JMock capable of dynamically mocking out each method?
My guess is no, as that would be pretty complicated. But knowing I'm barking up the wrong tree is valuable too :-)
The only thing I can think of is to have the create method on at factory object, which you would than mock.
But in terms of mocking a constructor call, no. Mock objects presuppose the existence of the object, whereas a constructor presuppose that the object doesn't exist. At least in java where allocation and initialization happen together.
jmockit can do this.
See my answer in https://stackoverflow.com/questions/22697#93675
Alas, I think I'm guilty of asking the wrong question.
The simple factory I was trying to test looked something like:
public Wrapper wrapObject(Object toWrap) {
if(toWrap instanceof ClassA) {
return new Wrapper((ClassA) toWrap);
} else if (toWrap instanceof ClassB) {
return new Wrapper((ClassB) toWrap);
} // etc
else {
return null;
}
}
I was asking the question how to find if "new ClassAWrapper( )" was called because the object toWrap was hard to obtain in an isolated test. And the wrapper (if it can even be called that) is kind of weird as it uses the same class to wrap different objects, just uses different constructors[1]. I suspect that if I had asked the question a bit better, I would have quickly received the answer:
"You should mock Object toWrap to match the instances you're testing for in different test methods, and inspect the resulting Wrapper object to find the correct type is returned... and hope you're lucky enough that you don't have to mock out the world to create the different instances ;-)"
I now have an okay solution to the immediate problem, thanks!
[1] opening up the question of whether this should be refactored is well out of the scope of my current problem :-)
Are you familiar with Dependency Injection?
If no, then you ceartanly would benefit from learning about that concept. I guess the good-old Inversion of Control Containers and the Dependency Injection pattern by Martin Fowler will serve as a good introduction.
With Dependency Injection (DI), you would have a DI container object, that is able to create all kinds of classes for you. Then your object would make use of the DI container to instanciate classes and you would mock the DI container to test that the class creates instances of expected classes.
Dependency Injection or Inversion of Control.
Alternatively, use the Abstract Factory design pattern for all the objects that you create. When you are in Unit Test mode, inject an Testing Factory which will tell you what are you creating, then include the assertion code in the Testing Factory to check the results (inversion of control).
To leave your code as clean as possible create an internal protected interface, implement the interface (your factory) with the production code as an internal class. Add a static variable type of your interface initialized to your default factory. Add static setter for the factory and you are done.
In your test code (must be in the same package, otherwise the internal interface must be public), create an anonymous or internal class with the assertion code and the test code. Then in your test, initialize the target class, assign (inject) the test factory, and run the methods of your target class.
I hope there is none.
Mocks are supposed to mock interfaces, which have no constructors... just methods.
Something seems to be amiss in your approach to testing here. Any reason why you need to test that explicit constructors are being called ?
Asserting the type of returned object seems okay for testing factory implementations. Treat createObject as a blackbox.. examine what it returns but dont micromanage how it does it. No one likes that :)
Update on the Update: Ouch! Desperate measures for desperate times eh? I'd be surprised if JMock allows that... as I said it works on interfaces.. not concrete types.
So
Either try and expend some effort on getting those pesky input objects 'instantiable' under the test harness. Go Bottom up in your approach.
If that is infeasible, manually test it out with breakpoints (I know it sucks). Then stick a "Touch it at your own risk" comment in a visible zone in the source file and move ahead. Fight another day.

Categories