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

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.

Related

#Autowired during testing

I have a question.
#Autowired annotation is not recomended since Spring Boot 2.x. Then I have to use constructor.
but in during testing (JUnit 5) i don't have any warning
Questions:
that means using #Autowired during testing is good practicle ?
JUnit and Spock(which is actually based on JUnit) frameworks are enforcing tests classes to have no-args constructors only. So it's not even achievable - probably that's why you weren't prompted about potential issue.
Test classes must not be abstract and must have a single constructor.
from junit documentation
To add a bit more to this article
Additional pros for constructor autowiring:
you can validate what kind of bean is being injected, either by code or by debugging tools if something suddenly stops working as expected.
it's easier to create class instance for testing purposes, especially if it has private/protected attributes that should be mocked and you are writing tests in pure java.
field injection is not recommended for a several of concepts, most of them connected to the usage of the class in other places, e.g the class can be instantiate with the default (no-args) constructor, thus will not be created with all or any dependencies
because the actual class can be instantiate in other places like at the testing part of code you get this warning
because the testing class usually isn't meant to be instantiate at any other parts of the code, you get no warning, this doesn't mean it's ok, it's still field injection and is still not recommended
you can read more about this here

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

java - testing - lambda with inner private method?

I have some problems with unit testing the following method.
public List<GetSupplyChainResponse> getSupplyChains(){
List<GetSupplyChainsResponse> response = new ArrayList<>();
supplyChainRepository.findSupplyChainsWithCompound().forEach(result
-> response.add(getGetSupplyChainSimpleResponse(result)));
return response;
}
getGetSupplyChainSimpleResponse() is a private method of the same class as getSupplyChains()
Is there any possibility to define return values therefore or do you have any other ideas how I could test the method getSupplyChains()?
You might be overthinking this. The fact that the method that you want to test (getSupplyChains) uses a lambda that calls a private method is irrelevant: they are just implementation details.
What you unit test is the part of your class that you as a client interact with, i.e. its interface. You typically call a public method with some arguments (in this case there are none), you get some return value and that is what you verify in your unit test. If your public method makes use of some private method, it will be tested also.
The problem here is that the response that you get from getSupplyChains obviously depends on what supplyChainRepository.findSupplyChainsWithCompound() returns. What you do in this case is mock that dependency (supplyChainRepository) out: you create a mock instance of SupplyChainRepository, you tell it how to behave, and you pass it to this class, for example via the constructor.
You can either write the mock yourself, or you can rely on a mocking framework to do the heavy lifting like Mockito.
I definitely recommend against unit testing private methods (it leads to brittle tests), or increasing the visibility of those methods (a.k.a. sacrificing your design for the sake of testing).
It is a commonly discussed problem, some prefer using reflection as Janos Binder recommended (How to call a private method from outside a java class), some can live with the fact the the visibility of the methods which we need to mock is increased for the sake of testability.
The problem is quite well discussed here: How do I test a class that has private methods, fields or inner classes?. You can see from the answers and wide discussions that the topic is quite complicated and developers split into factions and use different solutions.
I'd recommend you to remove the private access modifier and to make the method package private (use the default visibility). The common custom is to have the test classes in the same package (but not in the same folder!) as the tested classes.
This will allow you to:
Test the getGetSupplyChainSimpleResponse() method itself, which you should do in any case somehow.
Mock its behaviour for the purpose of testing getSupplyChains(). This you will achieve e.g. by using Mockito framework and its #Spy functionality.
For those who argue that this is "sacrificing your design for the sake of testing", I would answer that if you have private methods which need to be mocked and/or tested, then the design is not ideal anyway so changing the visibility to package private does not mean too big deterioration. The clear solution (from the object oriented design's point of view) is to delegate the behavior of such private methods to separate classes. However, sometimes in the real life it is just overkill.

Getting around setter injection using mockito's #InjectMocks

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.

Categories