Configuring state of mocked object for different scenarios - java

I've a DAO and a service class. In the service class CapService, I've #Autowired a reference of DAO class CapDAO. The CapDAO class has a private instance field of type int, that has it's value injected from a properties file using #Value annotation.
class CapDAO {
#Value("${someProperty}")
private int expiryTime;
}
class CapService {
#Autowired
private CapDAO capDAO;
}
There is a method - retrieveCap() in the CapDAO class, which retrieves the caps from the database, based on the expiryTime. That method is invoked from another method in CapService class.
The CapService class uses the list returned from DAO method to create another object wrapping that list. And finally it returns that data structure.
Now, I'm testing a scenario using Mockito framework. I've two scenarios. In both of them, I want to invoke method of CapService class, which will get me the object. The list retrieved form database, will depend upon the value of expiryTime in the CapDAO class. And so will the content of the object returned by CapService class method.
In test, I'm invoking the method in Service class, and checking the value returned. Since DAO is reading expiryTime from properties file, both the test scenarios cannot pass with the same configured value. I've to have two differently configured DAO instance to be injected into Service class.
So, my question is - is there any way I can configure the expiryTime in CapDAO class, to create two different instance, or may be in a single instance only, and inject those in CapService based on scenario? No I don't have any setter for expiryTime. Yes, I knwo I can use reflection, but I would like to keep that as my last resort.

Short answer
reflection is easiest possibility, you can simply use ReflectionTestUtil. Note: If you have an interface which CapDAO implements, you need also AopUtils
Long answer
If you don't wanna use reflection, you need separate your context and test to get this work:
// context1.xml
<context:property-placeholder location="classpath:test1.properties"/>
// context2.xml
<context:property-placeholder location="classpath:test2.properties"/>
Then you can define someProperty with some other value in the properties.
personally i will recommend reflection.

Related

Saving entities in private methods

I have an Ingestion class that exposes a single method ingest. This method processes each section of a passed in form (section 1, section 2, etc, etc).
I have private methods for each section, saving the entity as it processes through. I'm aware that #Transactional has no effect on private methods, however I do not want to expose these methods but would like to use the functionality that #Transactional provides.
I'm looking to make sure each section completes in its own Transaction; I could do this through 'AspectJ' (as other SO answers have suggested) instead of Spring's out the box implementation, but I am trying to avoid due to the system wide changes it would cause.
Any thoughts on another approach?
The pseudo code provided below gives a general idea on the structure of the class:
public Class Ingestion {
// Autowired Repo's
...
...
#Transactional
public void ingest(Form form){
this.processSection1(form);
this.processSection2(form);
this.processSection3(form);
}
#Transactional
private void processSection1(Form form){
// do specific section 1 logic
section1Repo.save(form);
}
#Transactional
private void processSection2(Form form){
// do specific section2 logic
section2Repo.save(form);
}
#Transactional
private void processSection3(Form form){
// do specific section3 logic
section3Repo.save(form);
}
}
=========================================================================
This is not a duplicate question as marked in the comments. I know #Transactional doesnt work on private methods. My question is more along the lines of 'how do we get around this Spring AOP issue without having to use AspectJ'
The reason this doesn't work is that annotations like #Transactional add additional functionality that is intercepted by Spring's proxy object that wraps the actual object. But when you call a private method on an object with the this keyword, you're going straight to the real object and bypassing the proxy.
One way to solve this is to #Autowire the object into itself, and make the transactional calls via that autowired variable. You can still access private methods that way, and the call will be to a Spring-managed proxy instead of the bare object.
You may extract these three processing methods in another class, make them public, but set the class constructor access level to package-local (but not private, since Spring can't proxy classes with private constructors), so no classes from other packages could access these methods just because they are not able to instantiate their class. It doesn't hide these methods completely, but may fit your needs. This trick can be done with an inner class as well (note that it must be declared with package-local access).
To completely hide these methods, you may make use of declarative transaction management by injecting TransactionTemplate bean and using its execute method in private methods. This feature comes out-of-the-box. See more here.
Also, take note that for creating new transaction on executing method B from method A, method B must be declared #Transactional with propagation type REQUIRES_NEW. Otherwise, any nested methods will be invoked in the same transaction started by initial calling method.

Create an object of a java class whose constructor is annotated with #Autowired

There is a class whose constructor is annotated with #Autowired. I want to create an object of this class without actually passing the constructor parameters and using the default parameters. Can someone tell me how can i create an object of this class?
One of the reasons of using Spring framework is you don't create objects and manage them manually spring does it for you.If you can give some more details example code or something it will help to understand your situation better.
Spring is a dependency injection framework (it does hosts of other stuff as well). So the whole point is not to "create" your own instances and re-use the instances that Spring has created for you.
If you want create object of class whose constructor is marked as #Autowired then still you can create object of that class using normal new java operator.
You can create an object of that class by just marking your field with #Autowired.Spring handles object creation for you.

Can JMockit initiate mock objects with argument constructor?

When I put the #Mocked annotation on a object which has only constructor with parameters, will this object be initiated rightly?
When I put the #Mocked annotation on a object which has only constructor with parameters, will this object be initiated rightly?
No.
A mock will be created that has the same interface. That means it will have the same public methods and if the test class is in the same package it will also have the same protected and package private methods accessible.
This mock will not invoke the real methods of the mocked class (unless you configure it so).
This means that for every method that is expected to be called by your code under test (cut) and that has a return value defined you have to configure your mock so that is returns a value your cut shall work with in that particular test.
This configurable return values and the verify capabilities of the mocks are the reason why we use mocking frameworks.
Attention
If you want to mock the call to a method which accesses a member initialized by the mocked classes constructor you have to use the form
doReturn(SOME_VALUE).when(mock).methodToBeCalledByYourCut();
because the form
when(mock.methodToBeCalledByYourCut()).thenReturn(SOME_VALUE);
will raise a NullPointerException in that special case.

How to get service according value with pattern?

I want according to role value, to get associated service, like
LogisticsUserEntity user = this.getLogisticsUserById(userId);
UserDealService userDealService = getUserDealService(user.getRole());
UserEntity userEntity = userDealService.getUserEntity(user);
LogisticsUserDao and TruckOwnerDao both implement UserDealService interface.
If role is 4, driverDao return, if it is 5, truckOwnerDao return, but I have used
#Autowired
private DriverDao driverDao;
#Autowired
private TruckOwnerDao truckOwnerDao;
I don't want to use a map, like
put(4, driverDao);
because if I want to add other dao, I have to modify the code, it violates the open-closed.
So how can I solve the extend problem?
Thanks for all your help and suggestions in advance.
As it was already mentioned in comments, you need a factory, but there are few factories.
Factory - Creates objects without exposing the instantiation logic to the client and Refers to the newly created object through a common interface. Is a simplified version of Factory Method
Factory Method - Defines an interface for creating objects, but let subclasses to decide which class to instantiate and Refers to the newly created object through a common interface.
Abstract Factory - Offers the interface for creating a family of related objects, without explicitly specifying their classes.
I would consider factory method, that way Your "user" object would have method "user.createUserDealService()" which returns needed service.
Yet I'm not sure if this should be called service, services are objects that are remote callable.
By the way it looks strange for getting userEntity based on user. Isn't user an entity already?

Google-guice: bind all instances of the same class to certain instance

I do not have a problem to bind singleton instance to some other instance using #inject.
But, when it comes to binding more instances of one class to some other instance (which is singletone) it refuses to bind it somehow and I'm getting null reference.
My code example is:
public class WebSocketManagerImpl implements WebSocketManager {
#Inject
private FactoryWebSocket factoryImpl;
}
When I create several instances of WebSocketManagerImpl, every factoryImpl field is null pointer.
Am I doing something wrong?
Please use Binding Annotations (https://code.google.com/p/google-guice/wiki/BindingAnnotations). This way you can annotate multiple instances of same class, and then have them selectively injected.

Categories