토비의 스프링 3의 부록 CD에는 책의 1부와 2부에 나온 예제코드와 함께 springusergroup이라는 웹 애플리케이션 샘플이 들어있다. 이 예제는 2부에서 설명한 주요 스프링 기술, 특별히 @MVC를 적용해서 만든 웹 앱 예제이다. 스프링 처럼 다양한 기술 옵션을 가진 프레임워크를 단일 예제를 만들어가면서 설명하는 방법은 적절치 않다고 생각했기 때문에 책에서는 각 기술 옵션을 적용한 코드가 담겨있는 학습 테스트 코드가 주로 등장한다. 각 기술의 사용방법을 꼼꼼히 설명하기에는 이 방법이 적절하다. 그렇다고 동작하는 하나의 완성된 예제 애플리케이션이 없다는 것은 아쉬운 일이다.

그래서 springusergroup이라는 간단한 웹 애플리케이션 예제를 만들어 넣어 두었다. 애플리케이션 하나에서 선택할 수 있는 기술 옵션에는 한계가 있으니 모든 기술의 사용방법을 보일 수는 없겠지만, 그래도 가능한 다양한 방식의 접근방법을 보일 수 있도록 만들었다. 또, 책에선 살짝 언급만 하고 넘어갔더 몇 가지 기술과 접근방법에 대한 실제 구현 코드를 넣어두기도 했다. 예를 들면 스프링 JDBC를 사용해서 만든 DAO에 하이버네이트/JPA와 같은 lazy-loading을 적용해두었다. 이를 이용해서 Many-to-One관계의 엔티티를 일단 Many만 먼저 읽어두고 다른 계층에서 필요에 따라 One쪽에 접근하면 다이내믹하게 DB를 읽어서 실제 오브젝트를 가져오는 JDBC 기반 DAO 코드를 만들 수 있다.

이렇게 예제에 적용한 기술 중에서 미처 책에서는 설명하지 못했던 것들을 몇 번에 나눠서 설명할 생각이다.

 

오늘은 그 첫 번째인 테스트용 필드 주입 유틸이다.

컨테이너나 프레임워크에 의한 필드 주입은 Java5에 애노테이션이 등장하고, JEE5에 @Resource 등의 필드 레벨 애노테이션을 활용한 기술이 소개되면서 자연스럽게 보편화되기 시작한 기법이다. 스프링도 JEE5/EJB3에 적용된 애노테이션을 이용한 주입/설정 기술을 스프링 2.5에서 차용하고 발전시키는 과정에서 자연스럽게 필드 주입을 사용하기 시작했다. 필드 주입은 애플리케이션 코드에서는 사용되지 않지만 컨테이너의 DI작업에 필요하기 때문에 추가했던, 그래서 클래스를 지저분하게 만드는 수정자 메소드를 제거할 수 있게 해준다. 필드 주입을 사용하는 것이 반드시 수정자 메소드를 삭제하도록 강제하는 것은 아니다. 그래도 굳이 애플리케이션 코드에선 필요하지 않은 단순 주입용 수정자 메소드를 그대로 둘 개발자는 거의 없을 것이다. 설정 코드와 메소드가 존재하지 않는 private으로 정의된 필드가 처음엔 어색하게 보일 수는 있겠지만, 어짜피 초기화 코드 없이도 컨테이너가 알아서 오브젝트 초기화 작업을 수행해준다는 IoC개념으로 보자면 자연스러운 코드일 수도 있다. 게다가 @Autowired 같은 DI 애노테이션은 기본적으로 설정 필수 옵션이 적용되어 있어서, DI를 통해서 주입이 일어나지 않으면 초기화 에러가 발생한다. 애노테이션을 단순한 메타 정보가 아니라 하나의 기능을 가진 코드로 보자면 필드 주입을 통한 DI는 자연스럽다.

문제는 테스트다. 수정자 메소드를 개발자들이 번거롭게 생각하는 이유는 애플리케이션 코드에서는 직접 사용할 일이 없기 때문이다. 하지만 테스트를 생각하면 얘기가 달라진다. 자바는 언어가 후져서 DI를 하려면 프레임워크가 필요하다고 주장하는 일부 다이내믹 언어 개발자들의 궤변과는 달리 DI는 자바 언어의 객체지향적 특징 때문에 자연스럽게 만들어지는, 자바 언어만 있어도 간단히 적용할 수 있는 프로그래밍 모델일 뿐이다. DI 프레임워크는 보다 복잡한 엔터프라이즈 앱에서 편리하게 DI를 적용하기 위해서 선택적으로 필요한 도구다. 이를 증명할 수 있는 가장 좋은 방법은 스프링으로 만들어진 코드에 대한 단위 테스트를 살펴보는 것이다. 스프링 스타일의 코드는 단위 테스트를 작성하기에 편리하다. 스프링 없이도 자바 언어 만으로 DI를 이용해서 간단히 고립된 테스트를 만들 수 있기 때문이다.

스프링을 적용했을 때 애플리케이션 코드에서는 사용되지 않는 것처럼 보이는 수정자 메소드나 주입용 생성자 등이 꼭 필요한 이유는 바로 테스트 때문이다. 테스트를 애플리케이션 개발의 필수 프로세스로 생각한다면, 더 나아가서 테스트 코드를 애플리케이션의 빠질 수 없는 한 부분으로 생각한다면 수정자 등이 애플리케이션에서 사용되지 않는 다는 말은 틀렸다. 굳이 프로퍼티별로 개별 수정자를 만들지 않고 한 두 개의 초기화 메소드를 사용해도 좋다. 어쨌든 테스트 코드에서 컨테이너의 도움 없이도 직접 오브젝트의 의존 관계를 지정할 수 있는 DI 작업이 필요하고, 이를 위해서는 public 접근자를 가진 주입용 메소드가 필요하다.

여기서 필드 주입의 부작용이 등장한다. 필드 주입을 사용하면 이해하기 쉽고 간결하면서 컨테이너가 IoC/DI를 수행하기 위해서는 아무런 문제가 없는 코드를 만들 수 있다. 반면에 단위 테스트에서 (테스트용 컨텍스트를 만드는 스프링 테스트라면 상관없지만) 직접 DI를 하려면 문제가 된다. 그래서 필드 주입을 적용하고 수정자 메소드 생략까지 해버리면 단위 테스트를 할 때 난처해진다. 물론 테스트를 안만들거나 만들어도 통합 테스트만 한다면야 상관없겠지만.

 

필드 주입을 적용하면서 단위 테스트를 간단히 만들 수 있는 방법을 생각해보자.

첫 번째 방법은 수정자, 생성자 내지는 초기화 용 주입 메소드를 만드는 방법이다. @Autowired 등은 필드에 적용하지만 수정자를 따로 만들어 두는 것은 아무 문제가 없다. 기존 수정자/생성자 주입만을 지원하던 시절과 비슷하게 테스트 코드를 작성할 수 있다. 이 방법을 사용할 때는 주입을 위한 수정자를 만들지 않아도 되므로 수정자보다는 관련된 몇 개의 필드를 한번에 주입하게 해주는 초기화 메소드가 낫다. 수정자 메소드가 길게 늘어지자 않아서 코드를 보기도 좋고, 테스트 코드도 작성하기 편하다. 그렇다고 생성자 주입처럼 매번 한방 주입을 해야하는 부담도 없으므로 테스트 코드도 유연하게 만들 수 있다.

이 방법은 로드 존슨이 권장하는 방법이다. 2007년 샌프란시스코 QCon에서 로드 존슨의 스프링 2.5 소개 세션에 참석한 적이 있는데, 그때 로드 존슨이 필드 주입을 소개하면서 당부했던 것이 단위 테스트를 만들 생각이라면 수정자를 잊지 말라는 것이었다. 그렇다면 단위 테스트를 만들지 않아도 되는 것도 있을까? 물론 있다. DAO라면 그렇다. DAO는 단위 테스트 대상으로 적절하지 않고, DAO 단위 테스트는 대부분 가치가 없다. 따라서 DAO는 대부분 DB(Fake DB든 뭐든)가 연동되는 통합 테스트를 작성하는 것이 원칙이다. 따라서 DAO에 적용되는 DI는 @Resource DataSource dataSource; 처럼 필드 주입만을 사용해도 좋다. 반면에 테스트용 의존 오브젝트(주로 DAO)를 코드 내에서 직접 주입해서 고립된 단위 테스트를 만드는 것이 필요한 서비스 계층 코드라면 수정자를 만들어서 단위 테스트를 쉽게 만들 수 있게 해야 한다는 것이 로드 존슨의 당부.

두 번째 방법은 내가 예전부터 선호하던 방법이다. 필드를 private이 아니라 접근자가 아예 없는 디폴트 접근자(패키지 프로텍티드라고도 하는)로 만드는 것이다. 디폴트 접근자를 가진 필드는 같은 패키지 내의 클래스에서는 접근이 가능하다. 방법은 단위 테스트를 클래스와 같은 패키지에 만드는 것이다. 물론 테스트 클래스는 소스 위치가 아예 다르기 때문에 패키지가 같아도 문제는 없다. 이렇게 해두면 번거로운 방법을 사용하지 않고도 테스트에서 간단히 클래스의 필드에 접근할 수 있기 때문에 단위 테스트를 작성하기 편리하다. 디폴트 접근자에 대해서 알레르기가 있고, 죽어도 private으로 필드를 만들어야겠다고 한다면 사용하기 힘들겠지만, 조금 타협할 수만 있다면 제법 간단하고 유용한 방법이다.

세 번째 방법은 springusergroup 예제에 적용한 방법이다. 바로 필드 주입용 유틸 메소드를 사용하는 것이다. 스프링은 어떻게 수정자 없이 private 필드의 값을 수정할 수 있을까? 뭐, 자바에서 되니까 했을 뿐이다. 리플렉션을 이용하면 private으로 제한되어있는 필드, 메소드에 얼마든지 접근하고 실행할 수 있다. 그렇다면 컨테이너가 썼던 방법을 테스트 코드에서도 이용할 수 있지 않을까? 어짜피 컨테이너에서 일어나는 DI를 테스트 코드에서 테스트 용으로 재구성하는 것이 목적이니 못쓸 것도 없다. 자바의 리플렉션은 대체로 타입에 안전한 편이며 강력한 기능을 가졌고 사용하기도 간편하다. 새로운 코드(클래스)를 다이내믹하게 추가하는 것은 바이트코드 생성 등의 작업이 필요하므로 라이브러리의 도움이 필요하지만, 이미 존재하는 클래스와 코드에 접근하는 것은 한 두 줄의 코드면 충분하다.

아무튼 이를 이용해서 간단히 필드 인젝션을 지원하는 유틸 메소드를 만들어 두면 테스트에서 유용하게 사용할 수 있다. Springusergroup 예제에는 FieldInjectionUtils라는 이름의 클래스에 스태틱 메소드로 필드 주입용 메소드가 만들어져있다.

물론 잘 알려진 테스트 지원 라이브러리에도 리플렉션을 이용해서 필드의 값을 읽고 쓰는 기능을 찾을 수 있다. 하지만 필드 이름을 지정해야 한다는 것이 맘에 안들었다. @Autowired와 가장 유사한 주입을 하려면 타입에 의한 필드 선택과 주입이 가능해야 한다. 매번 이름을 지정한다는 것은 타입 안전성이 떨어지고 오타로 인해 실수하기 쉽다.

 

예를 들어보자. 다음과 같은 B타입의 오브젝트를 DI하는 클래스가 있다고 하자.

class A {
   @Autowired B b;
   …
}

이를 FiedInjectionUtils를 이용해서 테스트 코드에서 Test용 B를 주입해주려면 다음과 같이 만들면 된다. 스태틱 메소드는 미리 import되었다고 하자.

A a = new A();
inject(a, B.class, new B());

inject 메소드는 a 오브젝트의 필드 중에서 B 클래스 타입을 찾아서 new B() 오브젝트를 넣어준다.

물론 같은 타입이 두 개 이상일 경우에는 qualifier나 이름이 필요하다. Qualifier는 좀 복잡하고, 일단 이름을 지정하는 두 번째 메소드를 만들었다. A에 B타입의 b1, b2 두 개의 필드가 있다고 하고 그 중에서 b1에 목을 넣어야 한다면 다음과 같이 해주면 된다. mock()는 Mockito의 mock().

A a = new A();
inject(a, B.class, “b1”, mock(B.class));

 

Springusergroup 예제에는 세 가지 방법을 이용한 테스트가 등장한다. 스프링 컨테이너를 띄우는 통합 테스트와 수정자를 사용하는 단위 테스트, 그리고 필드 주입 유틸을 사용하는 단위 테스트이다.

유틸 메소드를 좀 더 다듬어서 한정자(qualifier)도 사용할 수 있게 해주고 본격적인 필드 주입 애노테이션 인식도 하게 해준다면 매우 매력적인 DI테스트용 코드를 만들 수도 있을 것이다. Inject()에 넣는 클래스 정보도 사실 생략 가능하다. 테스트를 위해서 의도적으로 주입하지 않은 필드에는 자동으로 Mokito 목을 넣어주는 기능도 좋을 것 같다. 목이 안전한 디폴트 리턴 값을 돌려주게 할 수 있다면 DI할 오브젝트가 많은 테스트에서는 매우 유용할 것 같다. 시간 날 때 조금씩 더 다듬어봐야겠다.

필드 주입 유틸의 구현 코드와 적용 예제는 책의 부록 CD에서 찾을 수 있다.

Related posts:

  1. [토스3] 스프링 JDBC DAO에 lazy-loading 기능 적용하기
  2. 토비의 스프링 3이 나오기까지 (12)
  3. [토스3] 스프링 3.0.4 <mvc:default-servlet-handler/>를 이용해서 UrlRewriteFilter없이 깔끔한 URL을 만들기
  4. 토비의 스프링 3이 나오기까지 (11)
  5. 토비의 스프링 3이 나오기까지 (9)
  6. 토비의 스프링 3이 나오기까지 (7)
  7. 토비의 스프링 3이 나오기까지 (6)
  8. 토비의 스프링 3이 나오기까지 (5)
  9. 토비의 스프링 3이 나오기까지 (3)
  10. 토비의 스프링 3이 나오기까지 (2)
  11. 토비의 스프링 3이 나오기까지 (1)
  12. 토비의 스프링 3 출간지연과 동영상 소식
  13. [토스3] 매핑 가능한 BeanPropertySqlParameterSource
  14. [토스3] 스프링 JDBC DAO에 lazy-loading 적용하기 (2)
  15. 스크린캐스트 – 테스트와 스프링

Facebook comments:

to “[토스3] 테스트를 위한 필드 주입 유틸”

  1. This website really has all of the information I needed concerning this subject and didn’t know who to ask.

  2. Excellent web site you’ve got here.. It’s hard to find high-quality writing like yours these days. I really appreciate people like you! Take care!!

  3. Good blog post. I absolutely love this website. Continue the good work!

  4. Pretty! This was a really wonderful post. Many thanks for supplying this information.

  5. Your style is so unique compared to other folks I’ve read stuff from. Many thanks for posting when you have the opportunity, Guess I will just bookmark this page.

  6. May I just say what a relief to uncover a person that genuinely knows what they’re talking about on the internet. You actually know how to bring a problem to light and make it important. More people should look at this and understand this side of the story. It’s surprising you’re not more popular given that you surely have the gift.

  7. This is a topic that’s close to my heart… Many thanks! Exactly where are your contact details though?

  8. Great information. Lucky me I discovered your website by accident (stumbleupon). I have book marked it for later!

  9. Right here is the right site for anybody who wants to find out about this topic. You know so much its almost hard to argue with you (not that I really will need to…HaHa). You definitely put a brand new spin on a subject that has been discussed for decades. Great stuff, just great!

  10. Great blog you’ve got here.. It’s hard to find good quality writing like yours these days. I seriously appreciate individuals like you! Take care!!

  11. Your style is very unique compared to other people I have read stuff from. Thanks for posting when you’ve got the opportunity, Guess I’ll just bookmark this site.

  12. Good article. I certainly love this website. Keep it up!

  13. that is the end of this article. Right here you

  14. magnificent issues altogether, you just received a brand new reader. What might you recommend in regards to your submit that you made some days in the past? Any certain?

  15. I went over this site and I conceive you have a lot of wonderful info, saved to fav (:.

  16. I couldn’t resist commenting. Perfectly written!

  17. You are my aspiration , I have few web logs and sometimes run out from to post .

  18. You have made some really good points there. I looked on the web for additional information about the issue and found most individuals will go along with your views on this site.

  19. Great post! We are linking to this particularly great content on our website. Keep up the good writing.

  20. Oh my goodness! Awesome article dude! Thank you so much, However I am experiencing troubles with your RSS. I don’t understand why I can’t join it. Is there anybody getting identical RSS issues? Anybody who knows the answer can you kindly respond? Thanx!!

  21. Everything is very open with a very clear description of the challenges. It was really informative. Your website is very helpful. Thanks for sharing!

  22. I’m impressed, I have to admit. Seldom do I encounter a blog that’s both equally educative and engaging, and let me tell you, you have hit the nail on the head. The issue is something which not enough men and women are speaking intelligently about. I am very happy that I found this in my hunt for something concerning this.

  23. You need to take part in a contest for one of the most useful blogs online. I’m going to recommend this website!

  24. You ought to take part in a contest for one of the most useful blogs on the internet. I am going to recommend this site!

  25. This is the perfect website for anybody who really wants to find out about this topic. You know so much its almost hard to argue with you (not that I really will need to…HaHa). You definitely put a fresh spin on a subject which has been written about for years. Excellent stuff, just excellent!

  26. I was looking through some of your content on this site and I believe this website is rattling informative ! Continue putting up.

  27. There’s definately a great deal to find out about this issue. I like all of the points you have made.

  28. Great web site you have got here.. It’s difficult to find quality writing like yours nowadays. I truly appreciate individuals like you! Take care!!

  29. Oh my goodness! Impressive article dude! Many thanks, However I am experiencing problems with your RSS. I don’t understand the reason why I cannot subscribe to it. Is there anybody else getting the same RSS problems? Anyone who knows the answer will you kindly respond? Thanks!!

  30. I think this is a real great article post.Much thanks again. Keep writing.

  31. I enjoy reading a post that can make people think. Also, many thanks for permitting me to comment!

  32. Some genuinely nice and utilitarian info on this website, as well I think the design contains wonderful features.

  33. There’s definately a great deal to find out about this topic. I like all the points you’ve made.

  34. I’m more than happy to uncover this page. I need to to thank you for ones time for this wonderful read!! I definitely savored every bit of it and I have you saved as a favorite to check out new information on your blog.

  35. I?d should verify with you here. Which is not something I normally do! I get pleasure from reading a publish that can make folks think. Also, thanks for allowing me to comment!

  36. Nice post. I learn something new and challenging on websites I stumbleupon everyday. It’s always helpful to read content from other authors and use a little something from their websites.

  37. I used to be able to find good info from your blog posts.

  38. I’d like to thank you for the efforts you’ve put in penning this website. I really hope to see the same high-grade blog posts by you in the future as well. In truth, your creative writing abilities has inspired me to get my own blog now ;)

  39. Greetings! Very helpful advice in this particular article! It’s the little changes which will make the biggest changes. Thanks for sharing!

  40. I must thank you for the efforts you have put in writing this blog. I’m hoping to see the same high-grade content from you later on as well. In truth, your creative writing abilities has encouraged me to get my own website now ;)

  41. Wow! This can be one particular of the most beneficial blogs We’ve ever arrive across on this subject. Actually Fantastic. I am also an expert in this topic so I can understand your effort.

  42. Great post! We will be linking to this great content on our website. Keep up the good writing.

  43. Right here is the right site for anybody who wishes to understand this topic. You understand a whole lot its almost tough to argue with you (not that I personally will need to…HaHa). You definitely put a fresh spin on a subject which has been written about for ages. Great stuff, just excellent!

  44. Hi there! I simply would like to offer you a big thumbs up for the great info you have got right here on this post. I am coming back to your web site for more soon.

  45. This site truly has all the information I needed concerning this subject and didn’t know who to ask.

  46. You made some good points there. I looked on the internet for the topic and found most people will agree with your site.

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