I have been having a query regarding writing unit tests for web methods which actually communicates with a database and returns some value.
Say for example I have a web service named "StudentInfoService". That web serivces provides a API "getStudentInfo(studentid)"
Here is some sample snippet
public class StudentInfoService
{
public StudentInfo getStudentInfo(long studentId) {
//Communicates with DB and creates
// StudentInfo object with necessary information
// and returns it to the caller.
}
}
How do we actually write unit tests for this method getStudentInfo? Generally how do we write unit tests for methods which involves a connection with a resource(Database, Files, JNDI, etc...)?
Firstly, the class StudentInfoService
in your example is not testable, or atleast not easily. This is for a very simple reason - there is no way to pass in a database connection object to the class, at least not in the method that you've listed.
Making the class testable would require you to build your class in the following manner:
public class StudentInfoService
{
private Connection conn;
public StudentInfoService(Connection conn)
{
this.conn = conn;
}
public StudentInfo getStudentInfo(long studentId) {
//Uses the conn object to communicate with DB and creates
// StudentInfo object with necessary information
// and returns it to the caller.
}
}
The above code allows for dependency injection via the constructor. You may use setter injection instead of constructor injection, if that is more suitable, but it usually isn't for DAO/Repository classes, as the class cannot be considered fully formed, without a connection.
Dependency injection would allow your test cases to create a connection to a database (which is a collaborator to your class/system under test) instead of getting the class/system itself to create the collaborator objects. In simpler words, you are decoupling the mechanism of establishing database connections from your class. If your class was previously looking up a JNDI datasource and then creating a connection, then it would have been untestable, unless you deployed it to a container using Apache Cactus or a similar framework like Arquillian, or if you used an embedded container. By isolating the concern of creating the connection from the class, you are now free to create connections in your unit tests outside the class and provide them to the class on a as-needed basis, allowing you to run tests inside a Java SE environment.
This would enable you to use a database-oriented unit testing framework like DbUnit, which would allow you to setup the database in a known state before every test, then pass in the connection to the StudentInfoService
class, and then assert the state of the class (and also the collaborator, i.e. the database) after the test.
It must be emphasized that when you unit test your classes, your classes alone must be the only systems under test. Items like connections and datasources are mere collaborators that could and ought to be mocked. Some unit tests would use in-memory databases like H2, HSQL, or Derby for unit-tests and use the production-equivalent installations of databases for integration and functional testing.
Try to use http://www.dbunit.org/intro.html.
Main idea - make a stub database with known dataset to run your tests and assert results. You will need to reload the dataset before runs to restore initial state.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With