SpringDAO를 이용하면 Hibernate를 이용하는 DAO를 쉽게 만들 수 있다. 핵심은 HibernateTemplate클래스를 이용한 template방식의 접근이며 DataSource DI가 가능하고 template접근이 용이하게 설계된 HibernateDaoSupport를 상속해서 쓰는 것이 일반적이다.

이런 DAO를 테스트 할 때 문제는 DAO라는 것이 그 본질상 Unit Test가 어렵다는 데 있다. 그 이유는 DAO라는 것이 결국 백그라운드에서 돌아가는 persistent 기능을 이용하는 stub과 같은 존재이기 때문에 Unit Test보다는 DB가 참여하는 Integration Test로 작성하는 것이 상식처럼 되어있다. 물론 DB액세스는 데이터준비의 어려움과 테스트 성능저하 등의 부가적인 문제를 가지고 있다. 그래서 Embedded DB갈은 것을 이용한 Fake DB를 사용하는식의 방법을 많이 이용한다. JDBC자체를 Unit Test하기 위한 몇가지 툴이 존재하기는 하는데 사용하기 불편하며 사실 SQL이라는 문장으로 주로 정보가 넘어가기 때문에 그 자체를 비교평가하기가 만만치 않다.

결국 많은 개발자들은 DAO테스트는 integration test로 해야한다는 것을 당연하게 받아들인다.

하지만 static한 query를 날리는 DAO말고 다이나믹한 query를 생성하거나 data logic등을 가지고 있는 DAO라면 Unit Test를 쓰고 싶은 욕심이 생길 수도 있다. Hibernate는 오래된 텍스트 기반의 SQL 또는 그와 유사한 HQL을 사용하지 않고 Criteria라는 OO기반의 Query object를 지원한다. Query의 모든 요소를 object형태로 표현할 수 있기 때문에 dynamic query를 작성하기에 잘 맞으며 OO적이기 때문에 ORM의 구조와도 잘 연결된다. Object로 표현된 모델정보를 다시 HQL같은 텍스트로 표현해 놓으면 당장 리팩토링할때마다 텍스트를 다 찾아서 일일히 수정해줘야 하는 JDBC/Raw SQL을 쓸 때의 문제점에서 크게 벗어날 수 억다. 하지만 Criteria는 그런 면에서 월등하다. 그래서 Hibernate를 좋아하는 개발자들 중에는 그 선호하는 이유가 Criteria때문이라고 얘기하는 사람이 많다. 나도 그런 사람중의 하나이다. 특히 Hibernate 2.x에서는 Criteria가 HQL로 표현할 수 있는 모든 것을 다 표현하지 못해서 불편한 점이 많았는데 3.x에 와서는 거의 대부분의 기능을 다 Criteria를 써서 (심지어 Projection까지) 표현할 수 있기 때문에 더욱 애용되고 있다.

Criteria를 사용하는 코드를 Unit Test한다고 해보자. Criteria는 Session에서 만들어지는데 Unit Test를 하기 위해서라면 그 Session을 mocking하는 것이 필수이다. 하지만 코드에서 Session을 직접가져오는 구조라면 매우 어려울 수 밖에 없다. 하지만 Spring Dao에서는 Template을 이용한 Callback방식을 사용하고 Session을 그 Callback method로 전달해주는 구조로 되어있다. 따라서 이를 잘 활용하면 쉽게 DB와 연동 없이 Unit Test를 만들 수 있다.

간단히 다음과 같은 SpringDao기반의 Hibernate DAO코드가 있다고 치자

[java]
public class DaoImpl extends HibernateDaoSupport {
 public List findEntityByName(final String name) {
  return (List)getHibernateTemplate().execute(new HibernateCallback() {
   public Object doInHibernate(Session s) throws HibernateException, SQLException {
    Criteria c = s.createCriteria(Entity.class);
    c.add(Restrictions.eq(“name”, name));
    
    return c.list();
   }});
 }
 …
}
[/java]
findEntityByName이라는 메소드는 내부적으로 anonymous inner class방식으로 HibernateCallback인터페이스를 구현한 callback을 만들고 이를 HibernateTemplate의 execute로 전달한다. 내부에서 이미 시작된 Hibernate session이 있으면 이를 사용하고 없다면 새로운 session을 오픈한 뒤 이를 callback의 파라메터로 전달한다. 이 메소드를 unit test하려면 일단 HibernateTemplate을 먼저 mocking해야 한다. 다행히 HibernateDaoSupport는 HibernateTemplate의 setter를 제공한다. 다만 HibernateTemplate은 인터페이스가 아니고 클래스이므로 proxy를 만들거나 MockClass를 쉽게 만들 수가 없다. 방법은 HibernateTemplate을 상속해서 필요한 메소드를 override하거나 아니면 CGLIB등을 쓰는 방법이 있다. 테스트를 위해 만들어야 하는 메소드는 HibernateTemplate의 execute()이다. 내부적으로 Session을 만들어서 callback의 doInHibernate를 호출해주면 된다. 테스트하고자 하는 핵심은 결국 조건에 따라서 Criteria의 어떤 method를 호출하는 가를 검증하는 것이다. 주로 add(Criterion)메소드에 대해서 검증하는 방법을 쓰면 된다. 그러려면 Criteria를 mock으로 만들어야 한다. 하지만 Criteria는 직접 전달할 수는 없고 파라메터로 넘어가는 Session의 createCriteria를 이용해서 코드 내부에서 생성을 한다. 결국 Session, Criteria두개를 다 mock으로 만들어줘야 한다.

Callback의 내부코드가 실행되는 것을 테스트 해야하기 때문에 좀 복잡해진다. 물론 Callback을 독립적인 클래스로 만들면 별도로 테스트가 가능하겠지만 보통 anonymous inner class를 쓰기 때문에 hibernatetemplate부터 시작해서 3단계의 mock이 필요하다.

내가 만들어 본 것은 두가지 방법을 썼는데 첫째는 직접 클래스와 인터페이스를 이용해서 Mock클래스를 만들어서 쓴 것이다. Manual 방식으로 만들기에 적합한 케이스 중의 하나이다. 이렇게 만들어서 테스트 해본 것은 OSAF의 GenericHibernateDao에 적용을 했었다.

오늘은 이것을 EasyMock을 써서 한번 구현해봤다. EasyMock2.2에는 IAnswer라는 인터페이스를 써서 Mock이 리턴하는 값을 파라메터에 따라서 임의로 조종하게 하는 것이 가능하다. Mock으로 만든 HibernateTemplate의 execute를 실행할때 파라메터로 넘어오는 callback을 그 IAnswer를 구현한 클래스 내에서 직접 호출해주는 코드를 작성하고 그 파라메터로 역시 EasyMock으로 생성한 Session, Criteria의 Mock을 사용하면 된다. 그러면 간단한 Easymock코드를 통해서 callback내부의 코드에 대한 unit test가 가능해진다. 한가지 문제점은 Criteria에 조건으로 넣는 Criterion기반의 SimpleExpression들을 파라메터 비교를 해야하는데 이 바보같은 Hibernate는 SimpleExpression의 비교를 할 수 있는 equals를 구현해 놓지 않았다. 따라서 두개의 Restrictions.add(“a”,”b”)라는 것을 비교하면 다르다고 나와버린다. -_-. 그래서 찾은 방법은 toString을 이용하는 것인데 Hibernate의 scope of object identity개념을 생각하면 entity를 파라메터로 줘도 동일한 클래스이므로 identity비교만으로 두개의 비교가 가능하다. 이를 위해서 파라메터 matching을 위한 간단한 EasyMock 파라메터비교 클래스를 만들었다. SimpleExpression비교는 Hibernate에 이슈로 올려야겠다.

아무튼 그렇게 작성한 코드는 다음과 같다. HibernateTemplate을 mocking하기 위해서 EasyMock class extension을 함께 사용했다.

[java]
package caps.sample.test;

import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.getCurrentArguments;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;

import java.util.ArrayList;
import java.util.List;

import org.easymock.IAnswer;
import org.easymock.IArgumentMatcher;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Restrictions;
import org.hibernate.criterion.SimpleExpression;
import org.junit.Before;
import org.junit.Test;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;

public class DaoImplTest {
 DaoImpl daoImpl;
 HibernateTemplate mockHTem;
 
 @Before public void setup() {
  daoImpl = new DaoImpl();
  mockHTem = org.easymock.classextension.EasyMock.createMock(HibernateTemplate.class);
  daoImpl.setHibernateTemplate(mockHTem);
 }
 
 @Test public void testCriteria() {
  org.easymock.classextension.EasyMock.expect(mockHTem.execute((HibernateCallback)anyObject()))
   .andAnswer(new HibernateTemplateExecute());
  
  org.easymock.classextension.EasyMock.replay(mockHTem);
  
  List list = daoImpl.findEntityByName(“Toby”);
  assertEquals(1, list.size());
  
  org.easymock.classextension.EasyMock.verify(mockHTem);
 }
 
 static class HibernateTemplateExecute implements IAnswer {
  public Object answer() throws Throwable {
   HibernateCallback hc = (HibernateCallback)getCurrentArguments()[0];
   Session s = createMock(Session.class);
   Criteria c = createMock(Criteria.class);
   List expected = new ArrayList();
   expected.add(new Entity(“Toby”));
   expect(s.createCriteria(Entity.class)).andReturn(c);
   expect(c.add((Criterion)eqSimpleExpression(Restrictions.eq(“name”,”Toby”)))).andReturn(c);
   expect(c.list()).andReturn(expected);

   replay(s);
   replay(c);
   
   assertSame(expected, hc.doInHibernate(s));
  
   verify(c);
   verify(s);
   
   return expected;
  }
 }
 
 static SimpleExpression eqSimpleExpression(SimpleExpression se) {
  reportMatcher(new SimpleExpressionMatcher(se));
  return null;
 }
 
 static class SimpleExpressionMatcher implements IArgumentMatcher {
  SimpleExpression se;
  SimpleExpression realse;
  
  public SimpleExpressionMatcher(SimpleExpression se) {
   this.se = se;
  }

  public void appendTo(StringBuffer buf) {
   buf.append(“expected ” + se.toString() + ” but ” + realse.toString());
  }

  public boolean matches(Object o) {
   if (!(o instanceof SimpleExpression)) return false;
   realse = (SimpleExpression)o;
   return se.toString().equals(realse.toString());
  }
 }
 
}
[/java]

원하는 테스트는 성공적으로 잘 수행된다. EasyMock의 위력과 편리함을 잘 보여주는 케이스이다.

다만 테스트할 케이스가 많다면 코드가 불필요하게 길어질 것 같다.

그래서 Criteria를 사용하는 Hibernate Callback코드를 쉽게 테스트할 수 있는 Mock클래스를 하나 개발해야겠다는 생각을 하게됐다. Criteria에 조건을 어떤 순서로 넣었는지는 상관없이 파라메터에 따라 몇개의 restriction이 추가되고 모드나 추가 Criteria가 생성이 되었는지 쉽게 체크할 수 있는 그런 Mock을 하나 만들어봐야겠다.

사람들은 이래서 저래서 Unit Test만들기가 어렵다고 한다. 또는 어떤 경우들은 불가능하다고 한다. 하지만 내 경험으로는 Unit Test를 못만들 것은 없다. JUnit Recipe를 보면서 더 강하게 느낀 점이다. Unit Test에 안되는게 어딨니!

update: 그나저나 이 놈의 WordPress는 내 코드의 generic type부분을 태그로 생각해서 다 짤라먹어버렸군 -_-. 제대로 된 code를 표현할 수 있는 블로그로 바꾸고 싶다. ㅜㅜ

Related posts:

  1. spring과 hibernate 함께 쓰기. 그 만만치 않은 작업.
  2. AppFuse DAO Test 코드의 문제점
  3. Hibernate 3.0 released!
  4. Hibernate 3.2 GA 출시
  5. Spring+Hibernate+Eclipse로 .NET을 이기다
  6. Spring보다 많이 팔린 Seam, Wicket
  7. Hibernate In Action
  8. Hibernate 성능 & 최적화
  9. 학습테스트(Learning Test)를 이용해서 공부하기
  10. Spring 3.0 (19) Test 모듈의 선택라이브러리 분석
  11. Spring과 Google Guice의 협력을 통한 DI 애노테이션 표준화 작업 시작
  12. Hibernate vs. SpringFramework Again
  13. Hibernate Tips
  14. 테스트 코드에서 static import를 편하게 넣는 방법
  15. Spring Expressions(SpEL)를 이용한 Mockito Argument Matcher 만들기

Facebook comments:

to “Spring기반의 Hibernate DAO Unit Test 만들기”

  1. Testosterone Enanthate Research Chemical
    Seek advice from a hairdresser! There are several aspects of promoting the photo you should depict sometimes at home lifestyle or at the office. All the fancy garments in the world won’t compensate for an unsatisfactory haircut or style. Hairdressers are educated to provide the lower and design that you have to supply the graphic confidence other folks should conclude you will be capable.
    Anavar Recovery
    In the event you contact a credit score maintenance business and they also don’t provide you with a commitment to signal, they may be probably not legit as well as in truth a gimmick. You have to have a routine of fees presented to you along with a list of what services they’ll provide you for that fees you pay.
    Testosterone Enanthate Long Ester
    Should you be a male who is experiencing zits, make sure you are careful if you are shaving. By shaving over your zits areas, it is possible to inflame the facial skin round the impacted place and increase the risk for pimples to leave scars. Moreover, you could encounter a large amount of bloodstream out of this.
    Testosterone Pellets

  2. Equipoise 400 Meditech
    To help reduce swelling and ease lower back pain caused by muscles tension, attempt compressing the back muscle tissue. To compress the injured muscle tissue, think about using an elastic bandage or maybe a rear assistance. The action of compressing the muscle groups helps reduce the swelling from the muscle tissue. This, consequently, brings about an eliminating in back problems.
    Legal Injectable Steroids Uk
    If you have an individual arriving to think about your house, try to stay away from having a home loaded with men and women. If you have many people in your house, the consumer may experience like they may be an annoyance for you. They might hurry by your home rather than see every one of the attractiveness. It is best to maintain your residence friends at the very least through these times.
    Dianabol 1 Semaine
    Discover ways to use good affirmations to help you along with your anxiety. This could involve inspirational poetry, upbeat songs or just basic words that make you feel great about you. Take a moment and think about how you will would like time to visit and do what you must do so it will be a reality.
    Anavar Za Jeni

  3. Masteron Zns
    Aviation fans will enjoy this iPhone technique. Initially, you need to make sure that Location Providers are turned on in the phone’s Settings app. Following, teach Siri to inquire Wolfram which routes are over head. Siri will likely use data through the Wolfram Alpha google search to provide you with more information about any close by flight.
    Anadrol Anavar
    Whilst plenty of good reasons that people would like to quit smoking, there are even far more strategies and strategies that will help you do this objective. Produce a want to give up smoking and make use of the following tips that other people who smoke have tried to stop. You could find that understanding the right tips could make a big difference inside your good results.Planning A Property Facelift? Make Use Of This Information!
    Testosterone Cypionate Dosage Ftm
    Sometimes your jewellery is set in a substance known as shining marcasite. This kind of establishing ought to be cleansed by wiping a delicate, somewhat wet cloth across the stones along with the placing. It will then be right away dried by using a gentle micro-fiber fabric in order to avoid normal water spots or streaking. Never uncover shining marcasite to severe chemical substances.
    Anadrol Dosage For Beginners

  4. Testosterone Cypionate Gyno
    If a person wants skiing or wishes to personal some property that can provide an eye-catching function for renters they must take into account investing in a house that is in close proximity to well-known skiing regions. By purchasing real estate close to these areas one could attract tenants where you can place for their selves to work with.
    Boldenone Undecylenate Cycle
    Using tobacco is really a issue that many folks want to learn how to cease, yet the catch is they’re addicted and their brain is generally halting them from truly laying off. So utilize the suggestions with this article to remove that habit and stay a good life-style for the body.
    Thomas J Masterson
    You can’t go awry with a pair of tones. For those who have experienced a rough, sleepless evening, or perhaps you just don’t think that using makeup, hues will be your closest friend. By wearing them, you can conceal your swollen eyeballs, and they always add some type for any function.
    Testosterone Cypionate Effects On Blood Pressure

  5. Anavar 30 Mg
    Experiencing much more autos than a single demands is ways to spend more than one should be spending money on insurance plan. By offering or saving cars or anything else that one will not use frequently they will likely no more be forced to pay insurance plan on that vehicle. It would conserve them cash away from their insurance plan.
    Dianabol Use
    The easiest approach to finding careers on the web is to apply a task google search. This particular site indexes all of the work boards, enabling you to lookup all of them concurrently. I strongly suggest Without a doubt.com because it found my husband the position of his dreams!
    Mesterolone Tablet Brands In India
    Make use of a wines chiller. The flavors of wines modifications considerably with heat and each selection of red wine requires a particular servicing temperature for suitable style. The refrigerator by itself is not moving to have the right temperature ranges. Instead, invest in a vino chiller with built-in configurations for a variety of wine so you can get pleasure from each and every container to its maximum.
    Sustanon 250 Price In Mexico

  6. Masteron Koi
    Something that can be done to avoid acne is to lessen tension. The more pressure you will have the more likely pimples will bust out on the skin. Just one way of decreasing anxiety would be to exercising day-to-day. This will the two chill out your skin and promote circulation of blood also.
    Dianabol Cycle Dosage
    Look at offering purchasers a funds motivator. Even though your house is in excellent issue, the customers are likely to would like to modify something to make the home their particular. When you offer a income motivation within the bargain, it will let customers the opportunity produce a few changes at no cost to them selves. This makes your premises stand apart from other houses out there.
    Oral Steroids Make You Gain Weight
    Being a college student, you will want to decrease the amount that you simply dedicate to guides and items. Rather than getting textbooks on the university book shop, which can be normally at retail price, make buddies with upperclassman who can provide these books for much less. This could help you save a lot of money every semester.
    Npp A Masteron

  7. I think this is one of the such a lot vital information for me. And i’m satisfied studying your article. But wanna statement on some common things, The website taste is great,postcheap jerseys the articles is really nice D.Excellent task, cheers

  8. In the WordPress support forum, there are from time to time questions abut trackbacks. I haven’t used it myself, but I found a good tutorial on the OptiNiche cheap nfl jerseys china blog.

  9. I believe this website has some rattling wonderful information for everyone : D.

  10. I am the head web developer for the E-mail Extractor and Internet Search Engine Scraper by Creative Bear Tech – https://creativebeartech.com. In short, this online search engine scraper can scrape most of the search engines, featuring Google, Bing, AOL, Yandex along with social network sites platforms such as Facebook, Instagram, Twitter, LinkedIn, Yellow Pages, Google Maps and a lot more. I think it will be much easier if you browse through the complete tutorial at https://blockchainlifemag.com/2019/05/21/guide-email-extractor-and-search-engine-scraper-by-creative-bear-tech. The software program is not official yet, but immediately after it is, it will be accessible on https://creativebeartech.com We are presently beta testing the application and trying to find beta tester and software reviewers. You will receive the complete licence key for the software and can even scrape B2B contact information for your own specialized niche. If interested, please give me a shout on Facebook https://www.facebook.com/Creative-Bear-Tech-2284249764963533/or just reply to this thread.

  11. What do you guys make of Peaches and Screams I am looking to buy their Black Lace Bra and Waist Cincher Set with Panty as a Christmas pressie for myself :-RRB-

  12. Hi everyone! I was pondering if anyone wants to join me as a hemp and CBD goods reviewer? I have already received a ton of cbd product lines from most popular companies for instance, CBD For The People I likewise have a considerable amount of CBD and hemp goods to send to CBD and hemp reviewers, consisting of CBD Oil Syringe, CBD Edibles and CBD Supplements I also do vape reviews and am looking for a vape reviewer also to review the following eliquid labels (will be sent to you): Cake Monster E-Juice, Idiom E-Juice and Volcano E-Liquid Thanks guys and have a fab day! You can reach me at https://allcbdstores.com

  13. Good Afteroon I would like to invite you to register with Sweaty Quid, the best freelancer marketplace where you can hire freelancers for all your business needs and provide your own services for free. Get started right now and register at sweatyquid.com and If you have any questions, do let me know! Welcome to the mothership

  14. dapoxetin schweiz
    If you are considering looking at herbal treatment options to help you treat your joint inflammation signs and symptoms, remember that natural remedies are not regulated with the FDA. You should always speak with your physician and a skilled and experienced herbalist when thinking about the usage of herbal remedies.
    levitra kokemuksia
    In the event you can’t shell out your credit card harmony in full each month, make sure you make no less than double the amount minimal repayment till it is actually paid back. Spending merely the bare minimum will keep you held in increasing curiosity monthly payments for a long time. Doubling down on the minimal will help to ensure you get out of the debts at the earliest opportunity. Most significantly, stop with your bank cards for anything but urgent matters until the pre-existing debt pays off.
    priligy kopen
    Prior to buying property, you should spend time within the communities the at you are considering. Locals there are typically gonna tell you much more about what definitely occurs in the community than an agent who may be working on a payment that they can only get in case the deal shuts.
    kamagra wien

  15. viagra precio
    It is very important remember that telling your puppy “no” is not going to give him any information and facts. As an example, if somebody comes into your house, along with your canine begins to bounce, saying “no” will not be adequate information and facts. While, declaring, “sit” can be a greater choice, as it offers him anything he could actually do. If you explain to a dog what you need him with regards to a control, this eliminates uncertainty, and that he will be taught to listen.
    propecia prix
    Avoid employing any techniques that are set available by traders. You will find rarely any shortcuts that can be used to generate income with Currency trading, as it will probably be a thorough process to arrive at exactly where you need to be. Place the work in and you may get final results.
    acheter levitra
    Try to find achievable access points close to your home. Bugs and creatures are often very creative when it comes to busting into your house. If you have noticed a new difficulty, it really is probable that they found a whole new means by. Take a peek throughout the exterior and internal property and close any possibly entryways for unwanted pests.
    dapoxetine kaufen

  16. cialis netistä
    Keep your bone strong by increasing your calcium supplement consumption. Several older people crack hips and knees daily. Be sure that your your bones remain powerful with 2-3 servings every day of calcium supplements. Calcium mineral can be obtained from dairy foods, broccoli along with other vegetables. Shield your bone by feeding them.
    kamagra 100mg oral jelly
    When you have strained your again, prevent heavy shoveling. Shoveling mandates that you style and convert you again, which can trigger severe discomfort should you be already injured. In addition, the heavy body weight of your shovel can further more strain your muscle mass. Ask a pal to help you, or perhaps steer clear of the action till you are cured.
    viagra générique
    If you decide you want to start a online business, believe huge. Think of what your programs and targets are, determine the visions you may have, your motivation as well as your generate. Finding the bigger image will help to keep you motivated through the aggravating and painful occasions when you find yourself just commencing.
    viagra generico

  17. Hi guys

    I have spoken to someone from http://toby.epril.com/?p=195 regarding your listing on https://allcbdstores.com. The reason why your company has disappeared is because your listing has expired. You would have to create a new listing as the old listing was automatically deleted following a 30 day grace period at which it was not renewed.

    Regards

Leave a Reply

(required)

(required)

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

© 2017 Toby's Epril Suffusion theme by Sayontan Sinha