DAO test: the right way? - java

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.

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.

Test Retrieval from Data Structure without testing Store

Let's say I want to write some JUnit tests for a new, untested data structure BlackBox. It has an interface similar to a Map, but there's no way to tell what is going on inside of it:
blackBox.get(key);
blackBox.put(key, value);
How do I correctly unit test .get and .put in the two following scenarios? I cannot figure out how to test the two independently.
I am using TDD, and therefore want to write the tests first.
BlackBox has been written by someone else and I want to test it.
I know that if I had access to the source, I can do the following:
Whitebox.setInternalState(blackBox, "storage", storageObject);
assertEquals(blackBox.get("key"), expectedAnswer");
I can do the opposite to test .put(). The issue is that those tests rely on the implementation of the class.
So how can I individually test .get and .put without knowing or relying on the implementation details of the class?
I cannot figure out how to test the two independently.
why do you want to do that? does the contract state they are independent? i don't think so. i'm guessing the contract says:
new object is created as empty so get will return null / throw exception.
when you put something, you can get it.
you can not get what you didn't put.
when you put many times on same key you will get the latest value.
and so on. you can test each of those invariants. when you use Whitebox you start to test implementation details, not the contract and that makes the refactoring (e.g. using faster implementation) much harder

Test via JUnit DAO class

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

Test a non-idempotent method of a webservice

I am searching for a clean and simple way to write tests for a single non-idempotent method of a webservice. So far, I couldn't find a satisfying way to handle this.
For example, I have a DELETE method, which deletes entities in a database. It returns a 200 in case of successful deletion of the given entity. In the test, I call it with a specific entity id which is then deleted. In case of a second test run, it will fail, because the entity doesn't exist anymore.
To workaround that, I would need to put e.g. a POST call within the test, to create an entity before deleting it. But that's mixing up my API tests. So, if I get a test failure, I can't be sure whether the POST method or the following DELETE failed. If possible, I only want one single endpoint to be called in one single test.
Is there a better way to come around that? Does there exist a standard pattern?

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