Validating calls within a method using Mockito or jUnit - java

I'm working on some modifications to a DAO. The modifications included refactoring some code to keep a couple of methods from calling .getResultsList() multiple times. Instead, the results are cached to a List and all subsequent code works with that list making the code run more efficiently by only reaching out to the database once.
I was asked to create jUnit tests for the methods I modified to ensure that something like this won't happen again in the future. Is it possible for me to validate how many times a local variable inside a method has a function called on it using mockito?
I've seen several questions/forum posts on using verify to validate the number of calls made on a mocked object. But I don't actually have access to mock this object as it is being created inside the method any not being passed in.
Basically -
myDao has a class variable EntityManager called em, the em.createNamedQuery() function is stored to a TypedQuery variable q. This q is what .getResultsList was being called on multiple times.
In my jUnit test, is it possible to listen to what's happening inside the method I'm calling on my mocked Dao and make sure that q.getResultsList is only called once while the method is running?
UPDATE
myDao in my test class is configured using the #Autowired annotation like so:
#Autowired
MyDao myDao;
It is defined in the applicationContext.xml like so:
<bean id="myDao" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="com.mypackage.myDao"/>
</bean>
The method I'm calling is inside that DAO, so I call myDao.myMethod(myVar); Inside myMethod is the q variable I'm wanting to listen to. It's a local variable.

If you are mocking myDao then you aren't going to be able to validate code within myDao.
To test this you need a test for the myDao class. In that unit test you can mock EntityManager and have createNamedQuery return a mocked query. Then you can use mockito's verify and times(1) to verify that getResultsList() was only called once on the mocked query.

Related

Arquillian and TransactionAttributeType.REQUIRES_NEW

In my arquillian test a number of application methods are called, which either read data from the database or create data and persist to database. a) At some point a method annotated with #TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) is called. The test fails as the annotated method cannot find(on read it returns 0 records) some data persisted by some previous called methods(annotated with TransactionAttributeType.REQUIRED). Probably this is a normal behavior as a new Transaction opens. Reading the data in a previous called method and passing them as parameters to the annotated(TransactionAttributeType.REQUIRE) method works fine, but data should be read inside the REQUIRES_NEW method. Same problem appears in other tests when the TransactionAttributeType.REQUIRES_NEW is used. Is there a workaround to handle this case?
b) I've also mentioned that arquillian has issues with methods annotated with #TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED). It is like the code in these methods is not executed at all.
My current solution for both issues is to create a Mock class overriding the problematic methods. In case of b, the overridden method is annotated with #TransactionAttribute(TransactionAttributeType.SUPPORTS).
Try using flush() method and then refresh() of EntityManager before calling the method annoted with TransactionAttributeType.REQUIRED_NEW.

Spring Propagation.REQUIRES_NEW

In my understanding newPrint method in the following code should create a new transaction but apparently it prints out the same transaction-status object as was used in oldPrint method. I am calling oldPrint from another class. Is it because newPrint is being called using this? If yes, then when will a new transaction get created? If I call both methods from another class two separate transaction will be created anyway because #Transactional is used at class level.
#Transactional
public class Unsubcriber {
#Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public void newPrint() {
System.out.println(TransactionAspectSupport.currentTransactionStatus());
}
public void oldPrint() {
System.out.println(TransactionAspectSupport.currentTransactionStatus());
newPrint();
}
Output:
org.springframework.transaction.support.DefaultTransactionStatus#3bacd0e7
org.springframework.transaction.support.DefaultTransactionStatus#3bacd0e7
What would be the scenario when Propagation.REQUIRES_NEW would work?
Assuming geoand's edit clarification is true, the answer to your question is Spring uses AOP proxies to apply the transaction restrictions. So, this will work when calls come into you Unsubscriber from outside, which can then be intercepted and the transaction boundaries can be applied. If you're calling it from within your class, as you said, using 'this', then there is no proxying that can be done and hence your #Transactional will not come into play.
Here are few rules of #Transactional worth mentioning
1.#Transactional annotations only work on public methods. If you have a private or protected method with this annotation there’s no (easy)
way for Spring AOP to see the annotation. It doesn’t go crazy trying
to find them so make sure all of your annotated methods are public.
2.Transaction boundaries are only created when properly annotated (see above) methods are called through a Spring proxy. This means that
you need to call your annotated method directly through an #Autowired
bean or the transaction will never start. If you call a method on an
#Autowired bean that isn’t annotated which itself calls a public
method that is annotated YOUR ANNOTATION IS IGNORED. This is because
Spring AOP is only checking annotations when it first enters the
#Autowired code.
Source - http://blog.timmattison.com/archives/2012/04/19/tips-for-debugging-springs-transactional-annotation/
What you are seeing is a class misconception about Spring AOP.
Since newPrint() is being called from a method inside the same class, no advice is triggered and therefor no handling for transactional takes place.
Had you called the method newPrint() outside the class, a new transaction would be created whether or not the caller already participated in a transaction.
Since you have used #Transactional on the class, every method get's the default #Transactional settings and that is why you actually have a transaction.
Take a look at this section of the Spring reference documentation for a detailed discussion on how AOP works in Spring.
A total hack to get your code working like you expect would be the following:
((Unsubcriber ) AopContext.currentProxy()).newPrint();
This solution is mentioned in various places among which is this SO post.
Calling a method from within a class (using this) means that it will not go through the transaction initialisation contained within Spring's proxy object. Since the this keyword is a pointer to an instance of your original object, not the transaction aware, enhanced Spring object.
The annotations will work as expected in scenarios such as:
object1.oldPrint();
object1.newPrint();

TestNG Run all class methods multiple times preliminary doing #BeforeClass with supplied data

I'm writing a test suite for a webapp using TestNG and Selenium WebDriver.
What i need is to run all methods of the test class multiple times for different authenticated users (data is pulled out at runtime: from a DB). So i need to pass a data to the class with data provider, that supplies credentials of all users, then for each user i need to create a web driver (for the purity of the experiment) and authenticate with supplied credentials in #BeforeClass method, run all #Test methods of the class and make an #AfterClass tear down closing web driver.
How can i do that?
My attempts to do this are here:
https://gist.github.com/4246674
Attempt1 was to place a #Test(dataProvider="getUsersIdAndName") on class.
It doesn't work because as it turned out #Test(dataProvider=) on the class doesn't mean that all methods of the class should be invoked with the supplied data.
The result was that method wasn't invoked at all because there is no data to pass to it arguments. And i get strange test report where this method is marked as passed with execution time of 0 sec. (It is a Maven project opened in NetBeans, if this makes sense.)
Does #Test(dataProvider=) on the class means anything at all?
Attempt2 was to add dataProvider on the #Test annotation of the method.
It doesn't work because this means that test method is invoked twice during the single class run.
The result was that at the second time it fails because it tries to repeat the test while web driver wasn't reinitialized: browser already renders another page.
Also there are disadvantages of the first and second attempt that log in itself is done in test method rather that in #BeforeClass method because i know no way to supply it with data from data provider.
Attempt3 was a desperate attempt to combine #BeforeClass and #Test on the single method.
It doesn't work because #BeforeClass also demands #Parameters if an annotated method has a parameter list.
The result is that this method is invoked three times: first time as a class setup when it fails because of the above reason and two times because of the data provider when it succeeds.
Then i found out that TestNG doesn't provide a way to invoke all class methods multiple times with different data:
http://comments.gmane.org/gmane.comp.java.testng.user/864
I have two other ideas of how can i archive the same effect.
Idea4 is to place a #Test(dataProvider=) on each test method, each method will perform an authentication and isAuthenticated() test by itself and then perform it's own test.
Ineffective and ugly.
Idea5 that looks like the best affordable one is to mark with a #Test only one method that will aggregate all other test methods: it receives data from data provider, performs authentication by given user, then runs isAuthenticated test and all other necessary tests. In this case #BeforeClass and #AfterClass are only setting up and tearing down web driver. This approach has disadvantage that i'm loosing ability to use #BeforeMethod and #AfterMethod but this is affordable to me: looks like i will not need them.
Is there a better way to archive same effect?
Sorry for long message.
Thanks in advance.
You can try exploring Factory for your needs. Factory would allow you to run all methods annotated with #Test of a class with different data. You can initalize ur webdriver in ur beforeclass in that case. Explanation here.
Okay, let me try to answer your questions based on my experience with testNG and webdriver.
Q. Does #Test(dataProvider=) on the class means anything at all?
A. No. dataProvider is a method level annotation and not a class level. As mentioned here. It should be a method that supplies the data for the Test method in Object[][] format.
Q. How to achieve the scenario you have mentioned? (Assuming I understood your scenario..)
A. You should be using #BeforeMethod rather than #BeforeClass for instantiating webdriver object. In that way you can create a different WD object for each method. And dataProvider can pass multiple data to isAuthenticated() method. If you want to pass a config file at the class level, you can keep #BeforeClass with just property file loading logic in it. So that property file will be loaded once for the whole class. Obviously, you should also use #AfterMethod to close webdriver object.

How can I unit test this method in java?

I'm working with the Struts2 framework and would like to unit test the execute method below:
public String execute() {
setDao((MyDAO) ApplicationInitializer.getApplicationContext().getBean("MyDAO"));
setUserPrincipal(); //fetches attribute from request and stores it in a var
setGroupValue(); //
setResults(getMyDao().getReportResults(getActionValue(), getTabName());
setFirstResultSet((List) getResults()[0]);
setSecondResultSet((List) getResults()[1]);
return SUCCESS;
}
As you can see most of the logic is database related. So how would I go about unit testing this functionality? I would like to unit test by mocking a HTTPServletRequest with few request variables inside it.
My questions are:
How can I fake/mock a request variable as if its coming from a browser
Should my unit test be calling the actual DAO and making sure that the data is coming back?
If so, how can I call the DAO from unit test since the DAO is tied to the server since jndi pool settings reside on the application server.
I'd appreciate any book/article that shows how to really accomplish this.
The code you have shown us is not enough to fully answer your question.
Line by line
setDao((MyDAO) ApplicationInitializer.getApplicationContext().getBean("MyDAO"));
This is the hardest line since it uses static method. We would need to see how ApplicationInitializer works. In ideal world the getApplicationContext() method should return mock of ApplicationContext. This mock in turns should return MyDAO when getBean("MyDAO"). mockito is perfectly capable of handling this, as well as all other mocking frameworks.
setUserPrincipal(); //fetches attribute from request and stores it in a var
Where does the request come from? Is it injected to action class? If so, simply inject mocked request object, e.g. MockHttpServletRequest.
setGroupValue(); //
Same as above? Please provide more details, what this method actually does?
setResults(getMyDao().getReportResults(getActionValue(), getTabName());
Your previously created mock should return something when getReportResults() is called with given arguments.
setFirstResultSet((List) getResults()[0]);
setSecondResultSet((List) getResults()[1]);
I guess methods below set some field on the action class. Because you have full control over what was returned from mocked getReportResults(), this is not a problem.
return SUCCESS;
You can assert whether SUCCESS was the result of execution.
Now in general
How can I fake/mock a request variable as if its coming from a browser
See above, there is a mock built-in in Spring.
Should my unit test be calling the actual DAO and making sure that the data is coming back?
If your unit test calls real DAO, it is no longer unit test. It is an integration test.
If so, how can I call the DAO from unit test since the DAO is tied to the server since jndi pool settings reside on the application server.
This means you are doing integration testing. In that case you should use in-memory database like h2 so you can still run the test on ci server. You must somehow configure your application to fetch DataSource from different place.
Final note
In essence you should inject mocks of everything to your Struts action class. You can tell mocks to return any value upon calling. Then, after calling execute(), you can verify given methods were called, fields set and result value is correct. Consider splitting this to several tests.
Code review
Struts 2 integrates perfectly with Spring. If you take advantage of that functionality Spring container will automatically inject MyDAO to your action class. The first line becomes obsolete.
This code is hard to unit test because instead of using Spring as intended (i.e. as a dependency injection framework), you use it as a factory. Dependency injection is precisely used to avoid this kind of bean lookup you're doing, which is hard to test. The DAO should be injected into your object. That way, you could inject a mock DAO when unit testing your object.
Also, this logic is not database-related at all. The DAO contains the database-related logic. This action uses the DAO, and the DAO is thus another unit (which should be tested in its own unit test). You should thus inject a mock DAO to unit test this method.
Finally, this method doesn't use HttpServletRequest (at least not directly), so I don't understand why you would need to use a fake request. You could mock the setXxx methods which use the request.
Instead of simply mocking the HTTPServletRequest, how about
mocking an actual automated targeted request to the application
itself? Check out Selenium which lets you do just that.
For testing DAOs (integration testing), you could create your databases in memory using HSQLDB, which will allow you to create / delete objects from your tests, and making sure they are persisted / retrieved properly. The advantage with HSQLDB is that your tests will run much quicker than they will with an actual database. When the time comes to commit your code, you could run the tests against your actual database. Usually, you would setup different run configurations in your IDE to facilitate this.
The easiest way to make your injected daos available to your tests is to let your unit test classes extend AbstractJUnit4SpringContextTests. You could then use the #ContextConfiguration annotation to point to multiple xml application context files, or if you use annotation based configuration, point it to your context file which has the <context:annotation-config /> declaration in it.

Mocking at compile time

I'm working with some legacy code and I need to test that some expensive service is called (it makes network calls, send emails, etc.).
I'm able to inject a fake service instead of the original one by means of the framework in use (jboss seam 2). See this question: Mock #org.jboss.seam.annotations.in behaviour for unittest
I now want my fake object to be a smarter mock to assert if it has been called or not, etc. I would like it to be a Mockito or Easymock or some other thing mock. But constructing the mock the classical way in the test and then injecting it, is not working because of the way seam 2 and seam test deals with injection. See the link above.
Question: is there a way to have my mock extend or be annotated in order to become a Mockito or something mock? How can I get a reference to it in my tests?
I disagree with the answer of the question you linked to. A unit test should test the class independantly from the environment it's supposed to work in. And dependency injection frameworks are precisely used to be able to inject mock dependencies in unit tests, without needing any complex environment to run the unit test.
I don't know Seam, but its documentation says that #In can be placed on a property accessor. I would just have the class under test like this:
public class someBean implements Serializable {
private ApplicationBean applicationBean
#In
protected void setApplicationBean(ApplicationBean applicationBean) {
this.applicationBean = applicationBean;
}
...
}
And I would just call the setter to inject the mock in the unit test.
You could also let the code as is, but provide a setter or an additional constructor to be able to inject a mock applicationBean.
You need a class with the same name but a higher precedence. I've built plenty of mocks just doing that.
You give the same #name to your mock class and you define #install(precedence=MOCK). As soon as this class is in the classpath it will be used instead of your normal class (precedence default is application if I remember correctly).
I have no code ready here just now but I mock the facesmessage for example so during testing I can read these messages from this class and validate them.

Categories

Resources