Test via JUnit DAO class - java

I have a DAO class in which I need to test method called getItemById() which returns Item object from DB's table.
As long as I understand I have to make an Item object in that test and check if it equals to returned from method? Or I have to just check if it returns an Item object?
What if table is empty or no row with that id at all?
Sorry, this is a quite newbie question, but I can't make it clear in my head. Please help!

Running tests against a database where you can't predict what's in it is not effective; any test that is resilient enough to accommodate changing data is going to be worthless for the purpose of confirming whether the code under test actually does the right thing. I would make the test use its own database instance, so that there's no question of interference from other users mucking up my test, or my test changing data out from under somebody else. The ideal choice would be an in-memory database like H2, that the test can instantiate and throw away when it's done with it. That way the test can run anywhere (for instance on a CI server), with the same results.
The test needs to run the ddl to create the schema and populate the database before executing. There are different tools you can use for this. DbUnit is popular, there is also an alternative called DBSetup which is supposed to be less complicated. You can have separate test data for different scenarios. DbUnit has tools to extract data from a database to make it easier to create your test data.
Since the database is under your control and you can populate it as you wish, you should verify that the returned object's fields are what you expect based on the populated data. Make the test as specific as possible.
For testing the SQL and how the object is mapped to the resultset it makes sense to use a database. For some parts of this it would make sense to use a unit test that doesn't touch the database and uses mocks. For instance, it would be good to confirm that the connection gets closed in all cases, it's easier to use mocks than it is to cause a SQLException in your code.
Testing using mocks would be easier if the DBConnection class was injected instead of being instantiated within the method. If you changed the code to inject the DBConnection then you could write a unit test (one using mocks that doesn't use a database) that checks whether the connection gets closed.

To perform unit test you should walk by three steps:
Prepare test environement (eg. populate db with known test data)- so you wont ask is the table empty or not etc.
Perform test and assert result
Do cleanup - so test wont have influence on other tests
Besides, you should test all scenarios cuz you sholuld handle all of them

Related

Data dependent tests

I`m writing test for my "MySQL Requests Manager" and the problem is that some of the tests is depends on the data that contained in the database. So if any other test will delete the required records or someone else will delete them, that means that test will fail even if they correct.
I`m thinking about two approaches here:
1. In the test itself backup all the needed data before, run the test and restore the data from backup. But this is much more error prone and "heavier", in my humble opinion.
2. Before running one of the tests or even all of them is to create whole new database with structure and required data (from previously made dump, i think). This involves only around of two 'global' actions: create database and dropping it. Of course, i need to have totally isolated MySQL user and database for this.
What you think and what can you recommend? How another programmers dealing with that kind of issue?
Here's a different idea if you want to check it out: there's a java framework Mockito that is pretty helpful in cases like this. With it, you can create 'Mock' instantiations of certain objects/services that allow you to avoid actually instantiating them. With a mock, you can return a custom/hard coded results and test that your service handles that response correctly. For example, say you have a class 'SQLTestService' that has a method called 'getData()'. You can instantiate a Mock of 'SQLTestService' and have it return a specific value when 'getData()' is called. That way your tests are never actually dependent on the data in the DB and you can test for a specific outcome that you know your service should be able to handle.
When writing unit test, one should:
Use a test DB
Load data before each test (or load data before all tests)
#Before
public void setUp() {
//insert your test data here
}
Drop data after each test (or drop data after all tests)
#After
public void tearDown() {
// drop your test data here
}
That means the DB is system independent and each test runs isolated without having the fear of losing data, or interference between tests.

Is it enough to just instantiate other domain objects when you do unit testing?

If you test class Car, and want to create a method on it that returns the number of seats. Is it enough to just write car.addSeat(new Seat()) multiple times without actually setting some data on the seat if it isn't needed? The method would look something like:
public int numberOfSeats() {
return seats.size();
}
given that seats is a list of seats. Or would you fill data on the seat even though it isn't needed? Should you always just try to keep the effort on writing tests at a minimum?
You should consider using mocking. With mocking you can control how the object that's not being tested behaves using expectations.
e.g.
when(seat.getSomeProperty()).thenReturn("some value")
But if you don't need the value you can just leave the expectation out of your code. This way the code could be updated without rewriting the test and maintaing your test is much simpler.
Checkout Mockito
https://code.google.com/p/mockito/
I have two approaches in mind.
Define exactly what you want to test and you will know exactly what data needs to be filled. In your example, it wouldn't be neccesary to fill the seats.
If you want to test more than just numberOfSeats, you can use setUp and tearDown to create a reusable set of data for each of your tests. JUnit runs setUp before EACH test, and tearDown after.

DAO test: the right way?

I want to test my class MyTypeDAO implemented with Hibernate 4.1 using JUnit 4.9. I have the following question:
In my DAO, I have a findById method that retrieve an instance of my type by its ID. How to test this method?
What I've done:
I create an instance of my type.
Then, I need to persist this instance, but how? Can I rely on my saveMyType method? I don't think so, since I'm in the test case and this method is not tested.
Then, I need to call the findById method with the ID of the instance created in step 1.
Finally, I check that the instance created in step 1 equals the one I get in step 3.
Any idea? What are the best practices?
I have the same questions for the save method, since after running it, I need to retrieve the save instance. Here also, I don't think I can rely on my findById method since it's not already tested.
Thanks
One possible way is:
Create a in memory db for testing, load contents of this db from a predefined sql script andthen test your DAO classes against this database.
Everytime you start tests, database will be created from scratch using the sql script and you will know which id should return a result and which one should not.
See [DbUnit][1] (from satoshi's comment)
I don't think you have much choice to achieve this. It's not a good practice to have orthognal tests (tests that test 2 things or are dependent). Nevertheless, you should really consider this exception valid and fast. You are right : persisting an object and retrieving it is a good idea to test this dao layer.
Other options include having a record that you are sure about in the database and testing the retrieval (findById) on it. And the a second test to persist an object and removing it the teardown method.
But really, it would be simpler to test loading and saving together and it makes much sense.

Keeping tests to start with known state - What about multithreading?

I'm trying to cleanup my tests by always resetting to a known state before each test. In JUnit it seems that the best way to do this is to have a setup() method that sets the values for some fields. When running tests in parallel the field is always correct since each test is executed in a new instance of the test.
However in TestNG this doesn't seem to be the case. According to a post on their mailing list, setting fields in #BeforeMethod in a multithreaded testing doesn't guarantee their value.
As I need the classes I'm testing to be in a known state, is there a cleaner solution to this than using DataProvider or saying "Don't ever run tests in mulithreaded mode"?
There is only one difference between TestNG and JUnit in this specific area: JUnit will create a brand new instance of your test before each test method, TestNG will not.
What this means is that with TestNG, values stored in fields by test methods will be preserved between invocations, which is very useful if this object is complex and takes time to create. It also helps speed up test runs since you don't have to recreate this state from scratch every time.
If you want this state to be reset every time, simply put the initialization code in #BeforeMethod, like you do with JUnit (except it's called #Before).
As for multithreading, I don't understand why you are saying that there is no guarantee about that value, can you be more specific?

Help writing JUnit for JDBC

I created one class,in which i am inserting values into SQL as follows:
public class ABC{
some code here..........
...............
public void insertUsers(String firstName,String lastName,String location){
pre.setString(1,firstName);
I created test class for this class.
I want to write test case for this method insertUsers(),using assert statement.
how to write assert statement for above method.
When doing unit testing one should avoid accessing external resources such as databases, filesystems, network etc. This is to keep the tests in memory (fast), but also isolated from external failures. You only want to test a specific part of some functionality in e.g. a class, nothing else.
What this means for you is that the conn variable (I assume is the db connection) needs to be mocked out. You can do this easily with something like dependency injection, which means you pass in things into your class when constructing it. In this case you would pass in an interface which has the necessary functions conn uses.
Then in production you pass in the real db connection object while in test you pass in a mock which you control. Hence, you can then check that ABC calls and does what you expect it to do with conn. The same goes for pre you're using.
You can see it like this: I would like to test class ABC, and in order to do that I need to see how it uses pre and conn, so I replace those with my own test implementations I can check after doing something with ABC.
In order to specifically help you with what you're doing you need to show what pre is and tell us what you intend to test.
Well if you really want to test updating your database you can do that. Usually people follow one of the below two approaches -
Use Spring AbstractTransactionalDataSourceSpringContextTests This allows you to add any values to the database and then spring will take care and revert the values that you have inserted.
Use a seperate database Just for your JUnit tests. You really dont need anything heavy. You can use something like the HSQLDB which is really a lightweight java database. This will allow you to have separate test data from your production/QA database.
After the above is done(and you have run the insert statement) simply run select statement from your JUnit to get the data and then compare the previous data with the actual data.
A couple of remarks.
I'd use the standard assert during development only. It will check a condition and throw a runtime exception, if the condition evaluates to false.
If you expect illegal arguments, than it's much better to add some "normal" code to the method to handle those values or throw an IllegalArgumenException and write log entry.
Do not close the connection in this method! Do it only when you open/create the connection in the very same method. In larger applications you won't be able find out who closed the connection after a while. If the caller of insertUsers opened the connection, the caller should close it itself!
(more help possible if you tell us what exactly you want to test - the method parameters or if the insert was a success)
I wouldnt test the insertion of the data to the database, actually its not performant to access database during unittesting, this can be covered threw automated functional GUI testing tools of your application.
what you may want to test is the generation of the expected queries, this can realised if you seperate the geenration and the execution of the statements, you will be able to compare generated statements with expected ones without having to access you database from the unitest.

Categories

Resources