667514 members! Sign up to stay informed.

Sponsored Links


Resources

Enterprise Java
Research Library

Get Java white papers, product information, case studies and webcasts

News News News Messages: 41 Messages: 41 Messages: 41 Printer friendly Printer friendly Printer friendly Post reply Post reply Post reply XML XML XML

Article: Unit Testing with Hibernate

Posted by: Joseph Ottinger on April 08, 2005 DIGG
Unit-testing should have as few barriers as possible. For relational databases those barriers range from external dependencies (is the database running?) to speed to keeping the relational schema synchronized with your object model. For these reasons it is vital to keep database access code away from the core object model and to test as much as possible without touching a real database.

This article shows you how you can unit-test your Hibernate model, with a technique that should work for other O/R mappers as well.

Read Unit Testing with Hibernate

Threaded replies

·  Article: Unit Testing with Hibernate by Joseph Ottinger on Fri Apr 08 11:17:23 EDT 2005
  ·  DbUnit is really useful for database testing by John Hurst on Fri Apr 08 17:22:08 EDT 2005
    ·  AnyDbTest is the best DB unit testing tool I meet by Db UnitTest on Tue Apr 21 05:36:10 EDT 2009
  ·  Article: Unit Testing with Hibernate by Rod Johnson on Sat Apr 09 03:47:31 EDT 2005
    ·  Article: Unit Testing with Hibernate by John Hurst on Sat Apr 09 05:36:53 EDT 2005
      ·  Article: Unit Testing with Hibernate by Rod Johnson on Sat Apr 09 11:28:29 EDT 2005
        ·  Priming the database per-test vs rolling back after each by John Hurst on Sat Apr 09 14:19:13 EDT 2005
          ·  Priming the database per-test vs rolling back after each by Rod Johnson on Sat Apr 09 15:28:16 EDT 2005
          ·  Priming the database per-test vs rolling back after each by Agent Smith on Sat Apr 09 20:21:30 EDT 2005
          ·  Priming the database per-test vs rolling back after each by Howard D'Souza on Mon Apr 11 10:18:23 EDT 2005
            ·  Priming the database per-test vs rolling back after each by Rod Johnson on Mon Apr 11 12:39:41 EDT 2005
              ·  flush & clear by john lon on Tue Jul 01 19:26:59 EDT 2008
        ·  Article: Unit Testing with Hibernate by David Hay on Mon May 02 16:31:51 EDT 2005
          ·  quick way to make the dbunit data by Maulin Shah on Tue May 17 22:16:43 EDT 2005
    ·  unit test should make sure the code works by valraven smith on Sat Apr 09 11:15:59 EDT 2005
      ·  unit test should make sure the code works by Rod Johnson on Sat Apr 09 11:22:15 EDT 2005
      ·  unit test != JUnit tests != tests by Bostjan Dolenc on Sun Apr 10 05:04:48 EDT 2005
        ·  unit test != JUnit tests != tests by Rod Johnson on Sun Apr 10 06:39:27 EDT 2005
    ·  Article: Unit Testing with Hibernate by Dino V on Sat Apr 09 11:34:11 EDT 2005
    ·  Article: Unit Testing with Hibernate by Irakli Nadareishvili on Sun Apr 10 11:47:23 EDT 2005
      ·  Unit tests are the only fruit by Jonathan Gibbons on Mon Apr 11 04:55:00 EDT 2005
        ·  Unit tests are the only fruit by Irakli Nadareishvili on Mon Apr 11 09:41:50 EDT 2005
          ·  Unit tests are the only fruit by Irakli Nadareishvili on Mon Apr 11 09:49:33 EDT 2005
            ·  Unit tests are the only fruit by Jonathan Gibbons on Mon Apr 11 10:04:26 EDT 2005
              ·  Unit tests are the only fruit by Irakli Nadareishvili on Mon Apr 11 12:24:49 EDT 2005
                ·  Unit tests are the only fruit by Jonathan Gibbons on Tue Apr 12 10:22:43 EDT 2005
                ·  Unit test are the only fruit by Colin Lewis on Wed Apr 13 06:55:33 EDT 2005
      ·  Three types of test... by Erik Brakkee on Mon Apr 11 05:42:35 EDT 2005
        ·  Three types of test... by Twice Tshwenyane on Mon Apr 11 05:57:51 EDT 2005
        ·  Three types of test... by Irakli Nadareishvili on Mon Apr 11 09:26:33 EDT 2005
  ·  Rollback solution by Agent Smith on Sat Apr 09 20:27:13 EDT 2005
    ·  Rollback solution by Ingram Chen on Sun Apr 10 00:20:27 EDT 2005
      ·  Rollback solution by Rod Johnson on Sun Apr 10 05:39:41 EDT 2005
        ·  Rollback solution by Agent Smith on Sun Apr 10 05:48:54 EDT 2005
      ·  Rollback solution by Agent Smith on Sun Apr 10 05:40:18 EDT 2005
        ·  Rollback solution by Rod Johnson on Sun Apr 10 06:46:19 EDT 2005
          ·  Rollback solution by Agent Smith on Sun Apr 10 10:21:00 EDT 2005
            ·  Rollback solution by Anton Fedotov on Mon Apr 11 12:33:52 EDT 2005
  ·  Article: Unit Testing with Hibernate by Burak Bayramli on Wed Apr 13 01:30:57 EDT 2005
  ·  Article: Unit Testing with Hibernate by Phil Zoio on Wed Apr 13 09:36:21 EDT 2005
    ·  Article: Unit Testing with Hibernate by Rod Johnson on Fri Apr 15 07:14:10 EDT 2005
      ·  Article: Unit Testing with Hibernate by Phil Zoio on Mon Apr 18 05:29:20 EDT 2005
  Message #165443 Post reply Post reply Post reply Go to top Go to top Go to top

DbUnit is really useful for database testing

Posted by: John Hurst on April 08, 2005 in response to Message #165390
Hi,

I'm using Hibernate for DAOs in one project, and iBATIS in another. In both cases I'm doing unit tests of the DAOs. I find it very worthwhile to test the Hibernate/iBATIS mapping configuration.

These tests might also be described as "integration" tests, because I am running against the real RDBMS. I've considered using HSQL, but haven't so far because I'm worried the difference in SQL dialects would invalidate some aspects of the tests. For example, key generation could be different from my real database.

I use a test instance of the RDBMS. I use DbUnit extensively to set up my tests, and to verify results.

DbUnit can "prime" a database with test data from a very straightforward XML file.

Here's a simple example:

<dataset>

  <artists/>
  <branches/>
  <catalog_types catalog_type_id="C1000" description="1000 songs" />
  <catalog_types catalog_type_id="C2000" description="2000 songs" />
  <catalog_types catalog_type_id="NONE" description="None" />
</dataset>

Using DbUnit's CLEAN_INSERT operation with this file deletes all rows from catalog_types, branches and artists, then inserts the 3 given rows.

I often put a CLEAN_INSERT with a file listing all or most of my tables into the setUp() method of my test case. Then individual test methods may load further data. This helps isolate tests from each other - one test will not randomly break because of the state the database was left in by a previous test.

The only difficulty I've had with CLEAN_INSERT is that it can be tricky to get the ordering right for foreign key relationships. (Circular relationships are particularly tricky.)

DbUnit also provides methods to compare database data with expected data, which you can use to verify results of DAO or other operations. I use this to test DAOs.

I also use this feature to test non-trivial views in my database. I can set up a very simple DbUnit test case to populate the database with known test data that exercise the view, and then use DbUnit's verification to check that my view actually returns what I want it to. I've frequently had times on projects where a non-trivial view requires rewriting for optimization or other reason, and such unit tests can help verify the rewriting hasn't broken anything.

DbUnit provides a host of other useful features.

  http://dbunit.sourceforge.net/

John Hurst

Wellington, New Zealand

  Message #165473 Post reply Post reply Post reply Go to top Go to top Go to top

Article: Unit Testing with Hibernate

Posted by: Rod Johnson on April 09, 2005 in response to Message #165390
Important topic, interesting article.

As John points out, this is really integration testing, rather than unit testing. Unit testing should test classes in isolation and shouldn't depend on a database.

That said, I've found this form of integration testing hugely valuable on several projects, whether using Hibernate, JDBC or other data access solutions.

Some notes:

- I virtually always use the target database server (a development installation, of course). In the biggest project in which we used this technique, we were doing lots of smarts in Oracle triggers, views and stored procedures and trying to port enough of that to run meaningful tests against another database was unjustifiable. It also wouldn't have tested the stack correctly.

I don't think using a non-production database for testing is wise or necessary, except perhaps in prototyping. We used connection pooling in our integration tests with Commons DBCP. The supposed overhead of running against Oracle was virtually nonexistent after the pool was running. The saving running against anything else wouldn't have been worth it. (The only downside was that the team needed Oracle installed on their laptops due to some remote working, but that isn't a problem if the whole team are in the same office. Anyway, it's a false economy to give developers machines that can't run real software.)

- We used the Spring integration testing framework, which has been available since Spring 1.1.1. This is included in the spring-mock.jar in the org.springframework.test package and delivers the key features described in the article and more. Assuming that your application is already using Spring, it provides:
 - automatic creation and rollback of transactions so you don't need cleanup after each test case: this can save a lot of time
 - population of JUnit test cases by Dependency Injection, based on your Spring configuration. No need for explicit lookups in test cases
 - ability to manage Hibernate, JDO, JDBC, TopLink, iBATIS/whatever data access in the same transaction, ensuring correct rollback
- convenient JDBC helper instance variable to ease verification
 - caching of Hibernate or other configuration for the duration of the entire test suite to avoid repeated hits to parse the metadata

See the section in the Spring reference manual for documentation. The PetClinic sample app shipped with Spring includes an example using this with Hibernate.

Rgds
Rod Johnson
Spring from the Source

  Message #165480 Post reply Post reply Post reply Go to top Go to top Go to top

Article: Unit Testing with Hibernate

Posted by: John Hurst on April 09, 2005 in response to Message #165473
Hi Rod,

I should have mentioned, I'm using Spring also in both my current projects, and am a big fan :-)

I am using the Spring AbstractDependencyInjectionSpringContextTests base class to populate some of the beans in my DAO tests. I do find it a little frustrating that it's necessary to subclass in order to get this ... I haven't worked out a better alternative yet but I'm thinking about it. I don't like having to subclass an arbitrary 3rd party TestCase class, because (1) there are quite a few of them to choose from, and (2) I would prefer to have all my test cases, both unit and integration, extend a project-specific TestCase that I can put all my common project-specific assertions etc into.

This is one reason for example why I have avoided pursuing JMock and stick with EasyMock instead (for regular unit tests). As I understand it, JMock requires my test classes to extend their test class; EasyMock doesn't.

I looked at "automatic creation and rollback of transactions so you don't need cleanup after each test" provided by Spring. I've seen this approach advocated by a number of people, but I'm not sold on it. I understand the performance advantage. But to me, it kind of ruins test isolation. If you don't have each test prime the database in a reliable manner, you are risking running against an arbitrary, random database state. For the performance issue, my approach is to place my integration tests in a SlowTestSuite suite, which I don't necessarily run all the time in my IDE, but I _do_ run in my continuous integration tool (CruiseControl). So, the integration tests against the database may take ten minutes or even a little more; I'm still going to get my feedback reasonably quickly if something breaks.

Having said that, one of my projects uses Firebird for the database, and that's easy and lightweight to run locally on my laptop, so that's what I do. The other project is Oracle, and although I have run Oracle locally on my laptop, it is not that pleasant.

In either case, local or remote database, I'm pretty sold on DbUnit as a great way to manage and verify test data. The performance on a remote database can be pretty bad though.

Regards

John Hurst
Wellington, New Zealand

  Message #165495 Post reply Post reply Post reply Go to top Go to top Go to top

unit test should make sure the code works

Posted by: valraven smith on April 09, 2005 in response to Message #165473
> Unit testing should test classes in isolation and shouldn't depend on a database.

Couldn't disagree more. The test should make sure the code works. That's the goal. Isolation without the database is like isolating the testing a method without testing the entire class. It's nearly useless.

  Message #165496 Post reply Post reply Post reply Go to top Go to top Go to top

unit test should make sure the code works

Posted by: Rod Johnson on April 09, 2005 in response to Message #165495
Testing certain types of classes without database access--Hibernate DAO implementations for example--is nearly useless but that is not the case for most classes, which can and should be tested in isolation. And it doesn't change the definition of unit testing.

I think my post made it clear that I agree that testing using a database for Hibernate and other ORM-related code is valuable: it was merely a question of terminology.

  Message #165497 Post reply Post reply Post reply Go to top Go to top Go to top

Article: Unit Testing with Hibernate

Posted by: Rod Johnson on April 09, 2005 in response to Message #165480
John
I looked at "automatic creation and rollback of transactions so you don't need cleanup after each test" provided by Spring. I've seen this approach advocated by a number of people, but I'm not sold on it. I understand the performance advantage. But to me, it kind of ruins test isolation. If you don't have each test prime the database in a reliable manner, you are risking running against an arbitrary, random database state.
First, my personal experience has been that the performance advantage is huge with this kind of approach. So great that you won't want to go back to slower approaches. In a recent project we had around 200 integration tests (in addition to true unit tests), all of which hit the database via an ORM tool or JDBC and exercised a lot of functionality in Java and the database. These tests executed in Eclipse in around a minute--against Oracle--on an average spec developer machine. This made it possible to run the entire integration test suite, as well as unit tests, before committing changes to source control, and without leaving the IDE.

I understand your reservations about database state. The solution we've adopted is to have a set of reference data loaded by DBUnit or a database import which is the starting point. Then all the tests runs in their own transaction. When each is finished and the transaction is automatically rolled back, there's no impact on database state except a whack of sequence numbers used up. So nothing executes in a random database state, because once the initial seeding is done, the state is not altered by the test suite.

  Message #165498 Post reply Post reply Post reply Go to top Go to top Go to top

Article: Unit Testing with Hibernate

Posted by: Dino V on April 09, 2005 in response to Message #165473
I basically did the same approach as the article proposes but use spring to glue things together. I make sure that each domain object goes through crud operations and any specific hsql or sql in the DAO layer gets tested. I don't know how many times this approach has saved our butts because a developer would just rename a field in the domain object and not update the dependent hsql.

One thing that Rod is on the ball is that you should test against the target database server (i.e. don't test against mysql if your production is oracle). It will bite you. Even if you use standard sql or hibernate, there are always differences. I've read numerous articles advocating in-memory databases for the DAO testing. Even though it sounds great in theory it will definitely cause you pain later on.

  Message #165509 Post reply Post reply Post reply Go to top Go to top Go to top

Priming the database per-test vs rolling back after each

Posted by: John Hurst on April 09, 2005 in response to Message #165497
Hi Rod,

Thanks for your comments. I have to admit I haven't actually tried the rollback approach for myself--I guess I will have to now.

There are a couple of other concerns I had about the rollback approach, but I guess they are not insurmountable.

The pattern I've been using for Hibernate testing is to prime in one transaction, run the test code in a second, and verify results in a third. Yes, I can see it seems very expensive compared to the rollback approach. But it did seem straightforward and robust!

I put explicit transaction management into the test methods in order to keep Hibernate happy with lazy-loading. Now I think that was a mistake; the transaction management should be kept out of the test code (and put in the fixture instead) as a separate concern, just as with production code.

In my first project with DbUnit I used the "one dataset for all tests" approach. Of course, my mistake was trying to include the real data for the tests into this giant dataset, rather than just the common reference data. I had a lot of problems with different tests' data requirements conflicting with each other. Now I am probably erring the other way in striving for complete isolation.

Regards

John Hurst,
Wellington, New Zealand

  Message #165513 Post reply Post reply Post reply Go to top Go to top Go to top

Priming the database per-test vs rolling back after each

Posted by: Rod Johnson on April 09, 2005 in response to Message #165509
John
I put explicit transaction management into the test methods in order to keep Hibernate happy with lazy-loading.
Yes, some kind of transaction/connection management smarts is essential to effective integration testing. If you're using HibernateTransactionManager with Spring, of course, you can use the same transaction manager in test as in deployed environment, unless you need JTA for distribution or messaging. The test functionality I mentioned offers an endTransaction() method which enables the transaction to be ended early, which is useful for checking lazy loading behaviour. But in general I agree with your later comment: transaction management should be treated largely as an aspect in test cases as in production code.

Rgds
Rod

  Message #165528 Post reply Post reply Post reply Go to top Go to top Go to top

Priming the database per-test vs rolling back after each

Posted by: Agent Smith on April 09, 2005 in response to Message #165509
In my first project with DbUnit I used the "one dataset for all tests" approach. Of course, my mistake was trying to include the real data for the tests into this giant dataset, rather than just the common reference data. I had a lot of problems with different tests' data requirements conflicting with each other. Now I am probably erring the other way in striving for complete isolation.RegardsJohn Hurst,Wellington, New Zealand
This was a big mistake in our projekt too in the beginning. "One size fits all" does not work for test data. Each business logic test needs its OWN set of data. Otherwise you will have "spaghetti" test data.

The side effect of "each test creates its own data and deletes it afterwards" is that the database performance is not good. We use Oracle. It would be good if Oracle could act like an in-memory database.

  Message #165529 Post reply Post reply Post reply Go to top Go to top Go to top

Rollback solution

Posted by: Agent Smith on April 09, 2005 in response to Message #165390
I don't let tests rollback after they finished.

I use a so called "EntityGarbageCollector". The created entities are added to it. At the end of the test you simply write: garbageCollector.disposeGarbage().

The EntityGarbageCollector knows how to delete them.

  Message #165540 Post reply Post reply Post reply Go to top Go to top Go to top

Rollback solution

Posted by: Ingram Chen on April 10, 2005 in response to Message #165529
We use similar concept like EntityGarbageCollector (we call ObjectMother anyway...). At setUp() , add an Hibernate interceptor to intercept all saved persistent objects. At tearDown(), just delete all intercepted objects in reverse order. Such approach is a little bit slower than rollback solution. But this is quite useful when you need to do transaction-related integration test.

  Message #165550 Post reply Post reply Post reply Go to top Go to top Go to top

unit test != JUnit tests != tests

Posted by: Bostjan Dolenc on April 10, 2005 in response to Message #165495
<blockqute>Unit testing should test classes in isolation and shouldn't depend on a database.
Couldn't disagree more. The test should make sure the code works.Rod is talking about unit tests (definition).

But I agree that unit tests are rather useless when dealing with typical enterprise apps. The code doesn't do much on its own, but instead depends on myriad of external systems to do much of the "work". That's even more evident when dealing with databases (unless you take the intense ORM route, which is another can of worms).

  Message #165554 Post reply Post reply Post reply Go to top Go to top Go to top

Rollback solution

Posted by: Rod Johnson on April 10, 2005 in response to Message #165540
We use similar concept like EntityGarbageCollector (we call ObjectMother anyway...). At setUp() , add an Hibernate interceptor to intercept all saved persistent objects. At tearDown(), just delete all intercepted objects in reverse order. Such approach is a little bit slower than rollback solution. But this is quite useful when you need to do transaction-related integration test.
Interesting approach, but I can see some potential problems in complex apps. It's Hibernate-only, for example. What about JDBC updates/stored procedures? Triggers that Hibernate doesn't know about that do additional INSERTS, such as change tracking, on Hibernate operations? With the rollback approach all this works cleanly. All these are real examples from recent client projects, by the way.

  Message #165555 Post reply Post reply Post reply Go to top Go to top Go to top

Rollback solution

Posted by: Agent Smith on April 10, 2005 in response to Message #165540
We use similar concept like EntityGarbageCollector (we call ObjectMother anyway...). At setUp() , add an Hibernate interceptor to intercept all saved persistent objects. At tearDown(), just delete all intercepted objects in reverse order. Such approach is a little bit slower than rollback solution. But this is quite useful when you need to do transaction-related integration test.

And, when debugging, you see the intermediate results in the database with a tool like Toad. Only if data are committed, Toad shows the data. DBVisualizer let you change the connection to dirty read, but it didn't work in my case.

We don't use Hibernate (instead we use a bad home grown persistance framework on top of Entity Beans). So some things might be different.

  Message #165556 Post reply Post reply Post reply Go to top Go to top Go to top

Rollback solution

Posted by: Agent Smith on April 10, 2005 in response to Message #165554
What about JDBC updates/stored procedures? Triggers that Hibernate doesn't know about that do additional INSERTS, such as change tracking, on Hibernate operations? With the rollback approach all this works cleanly.
This can be a problem, but it isn't in our case.

We are not allowed to write data with JDBC. Only reading is allowed. For writing data we always have to use our persistance layer, which is a kind of ORM on top of Entity Beans. In order to be independant of the database, we are not allowed to use stored procedures.

Writing data with JDBC bypasses validation and can be dangerous. You only have very few database constraints like unique, not null, char length and so on. But our validation rules often contain much more constraints.

I must admit that I had to write data with JDBC (both DDL and DML) ... It was a table which simulated a database view. To remove the data I simply executed a DROP TABLE statement after the test finished.

  Message #165564 Post reply Post reply Post reply Go to top Go to top Go to top

unit test != JUnit tests != tests

Posted by: Rod Johnson on April 10, 2005 in response to Message #165550
But I agree that unit tests are rather useless when dealing with typical enterprise apps. The code doesn't do much on its own, but instead depends on myriad of external systems to do much of the "work".
My experience is that unit tests are incredibly useful, in all server-side applications, regardless of size and complexity. With appropriate design, you can limit the number of classes (like Hibernate DAO implementations) that cannot sensibly be tested in isolation. You can easily enough stub normal collaborators. I've experienced no difference in the value of unit tests between plain web applications and large financial applications. In fact in large financial applications, because they're mission critical and the impact of failure could be so costly, it's essential to maximize all forms of testing.

If you don't know whether each class is behaving correctly, it can get hard to diagnose problems in interactions. Did it correctly call the other classes? It's also easy to duplicate testing, without getting good code coverage.

But of course unit testing is just part of an overall testing strategy. No amount of unit testing will free you from the need to do lots of integration tests. But good unit tests will enable you to catch many problems earlier, and build a strong regression test suite.

Rgds
Rod

  Message #165565 Post reply Post reply Post reply Go to top Go to top Go to top

Rollback solution

Posted by: Rod Johnson on April 10, 2005 in response to Message #165555
And, when debugging, you see the intermediate results in the database with a tool like Toad. Only if data are committed, Toad shows the data.
True. However, you can easily verify using JDBC calls within the same transaction, before it gets rolled back. This has the advantage that it's verified by JUnit, whereas with Toad you're reliant on visual inspection. Of course Toad is a wonderful tool overall...couldn't live without it. But I like total automation for testing.

Rgds
Rod

  Message #165568 Post reply Post reply Post reply Go to top Go to top Go to top

Rollback solution

Posted by: Agent Smith on April 10, 2005 in response to Message #165565
Of course Toad is a wonderful tool overall...couldn't live without it. But I like total automation for testing.RgdsRod
I like total automation too for testing and I do it this way. But sometimes I have to debug my tests. I suggested Quest to improve Toad, so that I can dirty read for debugging.

  Message #165573 Post reply Post reply Post reply Go to top Go to top Go to top

Article: Unit Testing with Hibernate

Posted by: Irakli Nadareishvili on April 10, 2005 in response to Message #165473
Important topic, interesting article.As John points out, this is really integration testing, rather than unit testing. Unit testing should test classes in isolation and shouldn't depend on a database.

+1

Integration tests have their deserved place, indeed (just like other kinds of automated tests e.g.: user-experience tests, using SilkTest), but where a lot of people miss the point is that, even if you come up with the best set up to test with the actual DB, you _must_ still test your units in isolation and write enough of true _unit_ tests, too.

Quite a number of people say this is either 1) too hard 2) useless. Been there, done that and learned - that kind of thinking comes out of the lack of knowledge, nothing else. When you learn how to do the isolation properly, there will be no doubt left.

Isolated Unit-Tests and TDD are _very_ important for getting the design right and you can not afford to ignore them. "If they seem too hard for you, remember that ignorance is no excuse, learn how to do these things right and begin using!" - is what I tell my developers. :P

Dependency Injection, specificly - things that Spring provides and the EasyMocks project are truely invaluable in getting it "the right way". We owe these guys big time.

  Message #165635 Post reply Post reply Post reply Go to top Go to top Go to top

Unit tests are the only fruit

Posted by: Jonathan Gibbons on April 11, 2005 in response to Message #165573
I think you are advocating:
'No code will ever work unless you do unit tests'

Which is obvious lunacy. Given a choice of ONLY doing unit tests or ONLY doing integration tests which would you choose.

Obviously it's not a choice we have to make. But the answer makes you think (I hope).

Jonathan

  Message #165638 Post reply Post reply Post reply Go to top Go to top Go to top

Three types of test...

Posted by: Erik Brakkee on April 11, 2005 in response to Message #165573
I think it is key to have an object-oriented domain model (i.e. combining both behavior and data). In this way, the (complex) behavior of your application can be tested by unit testing different parts of your domain model, without requiring complex interactions with persistence.

Second, DAO interfaces should be used to make it easy to use a simple in-memory DAO where your unit test of the domain model requires it.

This results in three types of test: (1) unit test of your domain model, (2) unit test of your DAOs (e.g. testing your hibernate mapping), and (3) integration (unit) test of the combination. The last type of test will be relatively small comprising only a few tests since all the difficult parts were already tested before.

  Message #165639 Post reply Post reply Post reply Go to top Go to top Go to top

Three types of test...

Posted by: Twice Tshwenyane on April 11, 2005 in response to Message #165638
I think it is key to have an object-oriented domain model (i.e. combining both behavior and data). In this way, the (complex) behavior of your application can be tested by unit testing different parts of your domain model, without requiring complex interactions with persistence.
...

My thoughts exactly.

  Message #165656 Post reply Post reply Post reply Go to top Go to top Go to top

Three types of test...

Posted by: Irakli Nadareishvili on April 11, 2005 in response to Message #165638
This results in three types of test: (1) unit test of your domain model, (2) unit test of your DAOs (e.g. testing your hibernate mapping), and (3) integration (unit) test of the combination.
A correction, if you do not mind: current, agreed terminology in the literature and community: Unit Tests are only called tests that test a unit (mostly a class or its method) in isolation from anything else. Testing the DAO layer is a functional or integration test, depending on how you look at it: if you look at your DAO as a function/service of your app, or you look at it as integration between your App code and Database. Both views are valid.

  Message #165660 Post reply Post reply Post reply Go to top Go to top Go to top

Unit tests are the only fruit

Posted by: Irakli Nadareishvili on April 11, 2005 in response to Message #165635
I think you are advocating:'No code will ever work unless you do unit tests'Which is obvious lunacy. Given a choice of ONLY doing unit tests or ONLY doing integration tests which would you choose.Obviously it's not a choice we have to make. But the answer makes you think (I hope).Jonathan
Vincent Massol categorizes automated tests in 5 major categories. I, usually, like a little bit modified version of this categorization (mostly avoiding amibguosity in naming and making it more clear, at least for me)
1) Unit Tests - test only unit of code logi, in isolation from the rest of the application. Very fine-grained. Written by programmers.
2) Functional Tests - coarse-grained tests, validating some functionality of the application from the code-perspective (as opposed to "user tests"). Written by programmers.
3) Integration Tests - coarse-grained tests that test a public API of an application component from the specific viewpoint of how it integrates in the rest of the application. Written by programmers.
4) User Tests - tests that check the application functionality from a user perspective (not from the code-level). It's a click-click-works? kind of test that can (and should) also be automated using SilkTest (commercial, very solid) or Selenium (open-source, kinda fresh, yet). These tests are not written by programmers but rather by a QA person/team.
5) Load tests - checks performance.

All these tests, except the unit one, take significant amount of time to run. Therefore it is not adviced to run them at every build - that would decrease productivity of a programmer so much that s/he may stop testing completely. Except unit-tests, all other tests should, probabely, be run on dedicated test servers several times a day, in an automated fashion, and only alert programmer if something breaks. Unit tests, from the other hand, should be fast and programmers are adviced to run them at every build.

Also - only unit-tests have proven to have the special characteristics of aiding in the design process. They are the kind of tests that you mean when talking about the Tist-Driven Development. This is why they are very important.

Neverthless, if you ask me about the importance (and this is not my view so I am not gonna steal it) - automated user tests are the most important ones. So if you are going to have only one type - have them. Then the functional and integration tests come in the importance hierarchy. But as all of them are coarse-grained, statistically they only cover 70% of your code. And you must be aware of that. Also, as already mentioned, none of them aid in the design process.

This is why unit-tests are so important, not because they should be the only test types you write.

So, I am not as lunatic as one may think :)

What I try to say - all 5 types of tests (+ Porfiling, by the way) are very important and none of them should be ignored if you are serious about the quality of your application.

cheers

  Message #165662 Post reply Post reply Post reply Go to top Go to top Go to top

Unit tests are the only fruit

Posted by: Irakli Nadareishvili on April 11, 2005 in response to Message #165660
Clarification/addition to the above: functional/integration and user tests are both coarse-grained and, statistically, only cover 70% of the code. Unit Tests are fine-grained and combined with the rest of the tests can cover higher percentage of the code.

  Message #165667 Post reply Post reply Post reply Go to top Go to top Go to top

Unit tests are the only fruit

Posted by: Jonathan Gibbons on April 11, 2005 in response to Message #165662
I have seen a huge budget drained into consultancy cofers - and their dogma would include commandments such as:

"If they seem too hard for you, remember that ignorance is no excuse, learn how to do these things right and begin using!"

The dogma meant that clever people did as they were told and not what was right. The end result was a code base that could not integrate.

I agree unit tests are a powerful tool, on a par with a good integration/regression test suite.

Jonathan

  Message #165671 Post reply Post reply Post reply Go to top Go to top Go to top

Priming the database per-test vs rolling back after each

Posted by: Howard D'Souza on April 11, 2005 in response to Message #165509
I've been using the rollback approach, and I'm very satisfied with it. In addition, I've found it useful to explicitly flush the Hibernate session periodically, as this forces the SQL to be flushed to the database. Hibernate is smart about hitting the database, and will do so only when it needs to. If you don't flush, your entire test could be running against the level one cache.
Flushing allows you to catch errors in cascading parent-child operations, if the hibernate mappings are not set up correctly, foreign key constraints, database triggers, etc. Also, if your tests flush the session immediately after any database operation, you're more likely to catch problems closer to where they occur. The down side is that your tests will run marginally slower, which, to me, is not a big deal.
I tend to go with the more liberal interpretation of "unit test", where the goal is to ensure that a class works correctly in an environment closest to what it was intended for. To this end, I think it is necessary for any persistence related code to actually hit the data store, before I'm convinced that the code works.
Howard

  Message #165696 Post reply Post reply Post reply Go to top Go to top Go to top

Unit tests are the only fruit

Posted by: Irakli Nadareishvili on April 11, 2005 in response to Message #165667
I have seen a huge budget drained into consultancy cofers - and their dogma would include commandments such as:"If they seem too hard for you, remember that ignorance is no excuse, learn how to do these things right and begin using!" The dogma meant that clever people did as they were told and not what was right. The end result was a code base that could not integrate.I agree unit tests are a powerful tool, on a par with a good integration/regression test suite.Jonathan
Sorry, but I do not understand what your point it. Nobody is arguing with you that unit-tests should not be the only kind of tests, on the contrary I said if you can not have all of them, you should better concentrate on User Tests.

Yet, you keep to argue - what with? :)

That "dogma" you quoted just tries to reflect the reality that a lot of people try to avoid writing unit-tests because they are hard and lots of developers do not know how to properly do it. I am sorry if it sounded like commandment, but it really is a problem in the industry and ignorance is not an excuse, indeed.

  Message #165698 Post reply Post reply Post reply Go to top Go to top Go to top

Rollback solution

Posted by: Anton Fedotov on April 11, 2005 in response to Message #165568
I suggested Quest to improve Toad, so that I can dirty read for debugging.
If You work with Oracle database then its impossible
due to "consistent read" isolation level ;)
Just my 0.05$

  Message #165702 Post reply Post reply Post reply Go to top Go to top Go to top

Priming the database per-test vs rolling back after each

Posted by: Rod Johnson on April 11, 2005 in response to Message #165671
I've found it useful to explicitly flush the Hibernate session periodically, as this forces the SQL to be flushed to the database. Hibernate is smart about hitting the database, and will do so only when it needs to.
Good point. I forgot to mention that this is often essential.
If you don't flush, your entire test could be running against the level one cache.
Even flushing won't necessarily result in Hibernate requerying if you verify purely using Hibernate. So often it's good to flush then verify using JDBC, rather than (or as well as) Hibernate.

  Message #165849 Post reply Post reply Post reply Go to top Go to top Go to top

Unit tests are the only fruit

Posted by: Jonathan Gibbons on April 12, 2005 in response to Message #165696
Fair enough.

:)

Jonathan

  Message #165893 Post reply Post reply Post reply Go to top Go to top Go to top

Article: Unit Testing with Hibernate

Posted by: Burak Bayramli on April 13, 2005 in response to Message #165390
As a big time proponent of standalone (read -no server running-) kind of unit tests, I am sad to report that using HSQLDB for db access code has limitations. Especially if you are using complex HQL joins which translate into complex SQL joins, HQL barfs where you would have no problem with MySQL DB or more hard core databases. So I have modified our development environment setup so that now, it is mandatory to have a MySQL server running for every developer (on their local machine). This is not ideal but it at least conforms to KISS principle.

  Message #165940 Post reply Post reply Post reply Go to top Go to top Go to top

Unit test are the only fruit

Posted by: Colin Lewis on April 13, 2005 in response to Message #165696
I have seen a huge budget drained into consultancy cofers - and their dogma would include commandments such as:"If they seem too hard for you, remember that ignorance is no excuse, learn how to do these things right and begin using!" The dogma meant that clever people did as they were told and not what was right. The end result was a code base that could not integrate.I agree unit tests are a powerful tool, on a par with a good integration/regression test suite.Jonathan
Sorry, but I do not understand what your point it. Nobody is arguing with you that unit-tests should not be the only kind of tests, on the contrary I said if you can not have all of them, you should better concentrate on User Tests.Yet, you keep to argue - what with? :)That "dogma" you quoted just tries to reflect the reality that a lot of people try to avoid writing unit-tests because they are hard and lots of developers do not know how to properly do it. I am sorry if it sounded like commandment, but it really is a problem in the industry and ignorance is not an excuse, indeed.

The other strong argument for unit tests is refactoring. If you haven't got any unit tests then you can't by definition refactor. Most projects I've worked on have had core elements refactored several times even prior to go-live. Unit tests give developers the confidence to carry out major refactoring of both their own code and that of others (reinforcing the belief that every developer is responsible for the entire code base) safe in the knowledge that the code still works, at least well as as it did previously.

  Message #165966 Post reply Post reply Post reply Go to top Go to top Go to top

Article: Unit Testing with Hibernate

Posted by: Phil Zoio on April 13, 2005 in response to Message #165390
DbUnit can be very useful for managing a database test environment. This applies whether you're using it for Hibernate or any other data access technology.

It can also be useful for testing SQL queries, although it doesn't have support for parameterised SQL. You can't for example test SQL statements which have bind variables populated using PreparedStatement.setXXX() methods. This means that you can't really test your JDBC based DAOs with it, unless you're prepared to indulge in some trickery

Here's something which would really take DbUnit to the next level in unit testing Hibernate.

DbUnit has a the class
public class Assertion
{
    public static void assertEquals(ITable expected, ITable actual)
    public static void assertEquals(IDataSet expected, IDataSet actual)
}

which allows you to compare data from various sources, including a set of database, an SQL query, or the contents of an XML file.

Wouldn't it be great to have a mechanism to convert the result of a Hibernate query (a List containing an object graph) into an IDataSet object. You could then compare the Hibernate IDataSet with a fixture FlatXMLDataSet.

This conversion process should be configurable to NOT do any lazy fetching, so that the Hibernate IDataSet would only represent data returned from the 1st query (and not any lazily initiated subsequent queries).

This would allow you to do precise, concise and comprehensive tests of Hibernate queries with fairly minimal effort, and if implemented correctly, would properly test your fetch strategy implementation.

I might take a punt at implementing this myself when I have some time, but if anyone has tried this before it would save me the effort.

Cheers,
Phil Zoio

  Message #166339 Post reply Post reply Post reply Go to top Go to top Go to top

Article: Unit Testing with Hibernate

Posted by: Rod Johnson on April 15, 2005 in response to Message #165966
Wouldn't it be great to have a mechanism to convert the result of a Hibernate query (a List containing an object graph) into an IDataSet object. You could then compare the Hibernate IDataSet with a fixture FlatXMLDataSet.
Could be useful, but you would probably need to understand the Hibernate mapping metadata. How would you handle complex UserTypes for example?

Why not simply flush and then use JDBC to query, in the same transaction. That way you don't need to worry about metadata; both sides of your comparison are in the RDBMS representation.

  Message #166635 Post reply Post reply Post reply Go to top Go to top Go to top

Article: Unit Testing with Hibernate

Posted by: Phil Zoio on April 18, 2005 in response to Message #166339
Could be useful, but you would probably need to understand the Hibernate mapping metadata. How would you handle complex UserTypes for example?Why not simply flush and then use JDBC to query, in the same transaction. That way you don't need to worry about metadata; both sides of your comparison are in the RDBMS representation.

For testing write operations you could use session.flush(), then use DbUnit to validate changes - no problem.

For testing read operations and validating the data Hibernate is reading, using the metadata was the first way that came to mind, but definitely involves a lot of work.

The easier way is to intercept JDBC calls made by Hibernate, and use the Hibernate-generated SQL to build an IDataSet instance.

Writing tests could be done as follows:
1) create the Hibernate query and put it in your DAO
2) set up and load your test data
3) figure out the SQL that your Hibernate query should execute (most easily done by turning on Hibernate SQL logging and tweaking the HQL/Criteria until you get the SQL you're looking for.
4) use this SQL to generate a DbUnit XML data set file (e.g. "fixture.xml") from your test data
5) write your test. Your test will look something like this

public void testHibernateQuery()
{

//assume you've created session
//and instantiated DAO

HibernateDataSetCreator creator
= new HibernateDataSetCreator(session);

dao.setSession(session);
List data = dao.getData(... query params here ...);

IDataSet fixtureData =
new FlatXmlDataSet("fixture.xml");
IDataSet hibernateData = creator.getDataSet();
Assertion.assertEquals(fixtureData, hibernateData);

}

The important step is 3) - here's where you figure out what data your query should be returning to appropriately implement your fetch strategy.

Regarding implementation, the HibernateDataSetCreator would need to hook into the Hibernate/JDBC interface. This could be done in a couple of ways:
- using AOP
- replacing the JDBC driver with a proxy (a la p6spy)
- within Hibernate itself - provide a decorator for Hibernate's Batcher implementation, which could intercept JDBC calls. You'd need to tweak the SessionFactory configuration mechanism and override a couple of Hibernate internal classes to do it this way.

  Message #168820 Post reply Post reply Post reply Go to top Go to top Go to top

Article: Unit Testing with Hibernate

Posted by: David Hay on May 02, 2005 in response to Message #165497
Hi Rod,

How do you protect against adding data to the reference data that messes up some test that has already been written?

cheers,

David

  Message #170920 Post reply Post reply Post reply Go to top Go to top Go to top

quick way to make the dbunit data

Posted by: Maulin Shah on May 17, 2005 in response to Message #168820
i tend to use dbunit, but found it painful to
have to make the default data. so i wrote a quick and dirty
(very quick, very dirty) xsl that reads the *.hbm.xml files and makes a dbunit snippet for each table as:

<table>
<column>foo</column>
<column>bar</column>
<row>
<value>TEST-FOO</value>
<value>TEST-BAR</value
</row>
</table>

I wrote in ten minutes, so it can definitely be expanded to include the entire dtd and do fancy stuff. as it stands now it handles string, text as above, int/long/Integer/Long as 1, date as 2001-01-01 00:00:00, and discriminator columns as
DISCRIMINATOR. I can edit the data and copy and paste the row sets, but it still saves a bunch of typing and i can regenerate it when the mapping changes. i use a simple ant xslt task to invoke this.

note sure if code show up here, but here it is (you may need to view source?)

<code>

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 <xsl:output indent="yes"/>
<xsl:variable name="lcletters">abcdefghijklmnopqrstuvwxyz</xsl:variable>
<xsl:variable name="ucletters">ABCDEFGHIJKLMNOPQRSTUVWXYZ</xsl:variable>

<xsl:template match="/">
<dataset><xsl:apply-templates /></dataset>
</xsl:template>


<xsl:template name="rows">
<row>
<xsl:for-each select="id[@column]">
<value><xsl:attribute name="column"><xsl:value-of select="./@column" /></xsl:attribute>1</value>
</xsl:for-each>
<xsl:for-each select="discriminator[@column]">
<value><xsl:attribute name="column"><xsl:value-of select="./@column" /></xsl:attribute>DISCRIMINATOR</value>
</xsl:for-each>
<xsl:for-each select="property[@column]">
<value><xsl:attribute name="column"><xsl:value-of select="./@column" /></xsl:attribute>
<xsl:choose>
<xsl:when test="contains(./@type, 'String')">TEST-<xsl:value-of select="translate(./@column,$lcletters,$ucletters)"/></xsl:when>
<xsl:when test="contains(./@type, 'Date') and
not(contains(./@column, 'deleted'))">2001-01-01 00:00:00</xsl:when>
<xsl:when test="contains(./@type, 'Date') and
contains(./@column, 'deleted')"><null /></xsl:when>
<xsl:when test="contains(./@type, 'Integer')">1</xsl:when>
<xsl:when test="contains(./@type, 'Long')">1</xsl:when>
<xsl:when test="contains(./@type, 'int')">0</xsl:when>
<xsl:when test="contains(./@type, 'text')">TEST-<xsl:value-of select="translate(./@column,$lcletters,$ucletters)"/></xsl:when>
</xsl:choose></value>
</xsl:for-each>
<xsl:for-each select="many-to-one[@column]">
<value><xsl:attribute name="column"><xsl:value-of select="./@column" /></xsl:attribute>1</value>
</xsl:for-each>
</row>
</xsl:template>

<xsl:template match="class">
<table>

<xsl:attribute name = "name" ><xsl:value-of select="./@table" /></xsl:attribute>
<xsl:for-each select="id[@column]">
<column><xsl:value-of select="./@column" /></column>
</xsl:for-each>
<xsl:for-each select="discriminator[@column]">
<column><xsl:value-of select="./@column" /></column>
</xsl:for-each>
<xsl:for-each select="property[@column]">
<column><xsl:value-of select="./@column" /></column>
</xsl:for-each>

<xsl:for-each select="many-to-one[@column]">
<column><xsl:value-of select="./@column" /></column>
</xsl:for-each>

<xsl:call-template name="rows" />

</table>
<xsl:apply-templates />
</xsl:template>



<xsl:template match="joined-subclass">
<table>

<xsl:attribute name = "name" ><xsl:value-of select="./@table" /></xsl:attribute>
<xsl:for-each select="key[@column]">
<column><xsl:value-of select="./@column" /></column>
</xsl:for-each>

<xsl:for-each select="property[@column]">
<column><xsl:value-of select="./@column" /></column>
</xsl:for-each>

<xsl:for-each select="many-to-one[@column]">
<column><xsl:value-of select="./@column" /></column>
</xsl:for-each>

<xsl:call-template name="rows" />
</table>
</xsl:template>

</xsl:stylesheet>
</code>

  Message #260141 Post reply Post reply Post reply Go to top Go to top Go to top

flush & clear

Posted by: john lon on July 01, 2008 in response to Message #165702
We use setup in transaction.

To make sure our test hits the database and not just the L1 cache we flush and then clear the session.

  Message #307696 Post reply Post reply Post reply Go to top Go to top Go to top

AnyDbTest is the best DB unit testing tool I meet

Posted by: Db UnitTest on April 21, 2009 in response to Message #165443
I am glad to share one database unit testing tool. It is named as AnyDbTest (www.anydbtest.com). AnyDbTest Express edition is free of charge.

AnyDbTest is declarative style testing tool. We will not need to program at all. What we do is to express what we want to test, rather than how to test. We only need to configure an Xml test file to tell AnyDbTest what we want to test. Rather than painstakingly writing test code for xUnit test framework. So AnyDbTest is the right choice for DBA or DB developers.

AnyDbTest also offers a visual dashboard. Success or failure of test is automatically computed and presented to us via an easy-to-understand red/green light display.

Features specific to AnyDbTest:
*Writing test case with Xml, rather than Java/C++/C#/VB test case code.
*Many kinds of assertion supported, such as StrictEqual, SetEqual, IsSupersetOf, Overlaps, and RecordCountEqual etc.
*Allows using Excel spreadsheet/Xml as the source of the data for the tests.
*Supports Sandbox test model, if test will be done in sandbox, all database operations will be rolled back meaning any changes will be undone.
*Unique cross-different-type-database testing, which means target and reference result set can come from two databases, even one is SQL Server, another is Oracle.

New content on TheServerSide.comNew content on TheServerSide.comNew content on TheServerSide.com

Dependency Injection in Java EE 6 - Part 1

Reza Rahman explores the features of the proposed JSR 299, Contexts and Dependency Injection for Java EE (CDI). When approved, it promises to be a key feature of Java EE 6. (November 2, Article)

SAML: It's Not just for Web services

SAML is an XML-based standard for exchanging authentication and authorization data between security domains. The single most important problem that SAML was created to solve is the Web browser Single Sign-On problem. Many organizations are debating whether to stay with version 1.1 or move to 2.0. This article makes observations about both options. (September 28, Article)

Programming is Also Teaching Your Team

Joe Ottinger takes a look at how people learn, and applies it to the practice of programming. He notes that understanding how people learn is an essential part of working in a programming team. (September 22, Article)

Can Java EE Deliver The Asynchronous Web?

Stephen Maryka gave us an article about the Asynchronous Web and posed a number of questions that get examined like an approach to delivering Asynchronous Web capabilities through extensions to existing Java EE technologies. (July 14, Article)

JSF Flex

JavaServer Faces Flex goal is to provide users capability in creating standard Flex components, part of flexSDK which is open sourced through MPL license, as normal JSF components. This article by Ji Hoon Kim will provide an overview of creating a simple multilingual JSF page consisting of JSF Flex tags. (June 29, Article)

The Rules of SOA - A Road to a Successful SOA Implementation

In this session Jeff explores the key characteristics of successful SOA projects. He covers some of the patterns, and anti-patterns, tool sets, and strategies that he himself learned the hard way. Last, he provides a strategy and blueprint for achieving a high likelihood of success in your SOA project. (June 23, Tech Talk)

Ari Zilka Talks About Terracotta 3.1

Ari Zilka, CTO of Terracotta, Inc., talks about the new features in Terracotta 3.1, announced during JavaOne and available now. (June 15, Tech Talk)

Enterprise Application Integration, and Spring

In this Tech Talk, Josh Long explores an integration challenge using Spring Integration and walks through the implementation, employing and expanding on the basic patterns of Enterprise Application Integration to tie together components into a function integration solution, and then demonstrates how Spring Integration helps address the integration requirements. (June 15, Tech Talk)

Google Web Toolkit: An Introduction

In this Tech Talk, David Geary teaches you: The basics of Google Web Toolkit; How to implement Ajax-enabled applications in Java; Internationalization; Hooking into the browser history mechanism; Remote procedure calls. (June 4, Tech Talk)

Just Enough Early Architecture to Guide Development

Jon Kern discusses the best architecture/technical solutions and ensure that they are repeated by all developers. By tackling the architecture up-front in a serial manner, subsequent parallel development will be much more manageable and predictable. (May 28, Tech Talk)

Productive Programmer: On the Lam from the Furniture Police

This keynote describes the frustrations of modern knowledge workers in their quest to actually get some work done, and solutions for how to guard yourself against all those distractions. Neal Ford talks about environments, coding, acceleration, automation, and avoiding repetition as ways to defeat the misguided attempts to sap your ability to produce good work. (May 26, Tech Talk)

Auto-Scaling Your Existing Web Application

Gil demonstrates how new, aggressive uses of already abundant compute capacity by common applications offer competitive value for application designers. (May 21, Tech Talk)

Automating Hibernate Mapping and Queries For Java Web Development

Chris Keene introduces WaveMaker as a new way to automate the ability to generate Hibernate classes in order to more quickly bring OR mapping into an application. (May 19, Article)

Auto-Scaling Your Existing Web Application

In this session Nati Shalom demonstrates how to take a standard Java EE web application and scale it out or down dynamically without changes to the application code. Seeing as most web applications are over-provisioned to meet infrequent peak loads, this is a dramatic change because it enables growing your application as needed, when needed, without paying for unutilized resources. (May 19, Tech Talk)

Free Book PDF Download: Mastering EJB Third Edition

Mastering EJB was one of the original and most influential EJB books in the industry. Mastering EJB III now returns with two new expert co-authors, updated for EJB 2.1 and 30% new chapters including security, integration, best practices, open source, and more.
(Book PDF Download)

Application Server Matrix

The Application Server Matrix is a detailed listing of J2EE vendors and their application server products, with information on latest version numbers, J2EE spec support and licensing, pricing, platform support, and links to product downloads and reviews.
(Application Server Comparison Matrix)

News | Blogs | Discussions | Tech talks | Patterns | Reviews | White Papers | Downloads | Articles | Media kit | About
Java Solutions
All Content Copyright ©2007 TheServerSide Privacy Policy
Site Map