Mockito를 사용할 때 가장 아쉬운 것은 property를 확인하는 argument matcher가 없다는 것이다. 보통 오브젝트간에 주고 받는 파라미터는 단순 값들보다는 복잡한 오브젝트이다. 특히 DAO로 넘기는 것들은 대부분 도메인 모델/엔티티 구조이니 기존의 파라미터 오브젝트를 직접 비교하는 방법은 그다지 유용하지 못하다.

name, age라는 프로퍼티를 가진 User라는 도메인 오브젝트가 있다고 하자.

UserDao 인터페이스 타입의 목을 만들어서 테스트에 사용했다고 하자. 그리고 add(User u) 메소드로 넘어간 User오브젝트의 name이나 age가 어떤 값을 가지고 있는지를 확인하고 싶다면, 그리 간단치 않다.

verify(mockUserDao).add(…) 에 arguement matcher를 넣어서 검증해야 하는데, 스트링이나 기본형이라면 모르겠지만, 파라미터의 getName()으로 가져온 값을 바로 비교하게 만들기란 쉽지 않다. 결국 Custom Argument Matcher를 만들어서 사용해야 하는데, 이게 거의 커스톰 목 클래스를 정의하는 것 만큼 귀찮은 일이다.

그래서 EasyMock에서는 bean property를 비교할 수 있는 뭔가가 있는 것 같은데, 내가 쓰는 Mockito 1.7에서는 아직 발견하지 못했다. Hamcrest Matcher를 사용할 수 있지만, 거기서도 못찾았고. 아마 누군가 만들어둔게 있을거라고 생각하지만.. 더 찾아볼까 하다가 아예 발상을 바꿔봤다. 한번에 여러개의 프로퍼티를 비교해야 한다면 한 개 이상의 비교를 하려면 파라미터 타입을 어떻게 쓸지가 고민이다. 맵을 사용해야 하겠지만, 이놈의 Map은 한방에 정의하기도 힘들다. 왜 자바는 맵이나 해쉬를 언어차원에서 지원하지 않는지 원망스러울 때가 많다.

그래서 생각한 것이 바로 스프링 3.0의 익스프레션 언어지원기능. 왠만한 시중에 나와있는 EL류보다 월등히 뛰어나다고 자부하는 바로 그 것이다. 아직은 사용 시나리오나 용도가 많지는 않지만, 잘 사용하면 알게 모르게 편리하게 이용할 수 있다.

 

그래서 스프링의 EL을 이용한 argument matcher를 만들어봤다. 하는 김에 assertThat에서 바로 사용할 수 있도록도 만들었다.

SpEL의 막강한 기능 덕에 몇줄 안되는 코드로 손쉽게 작성이 가능했다.

 

package org.opensprout.commons.test;

import org.hamcrest.Matcher;
import org.mockito.ArgumentMatcher;
import org.mockito.Matchers;
import org.springframework.expression.EvaluationException;
import org.springframework.expression.Expression;
import org.springframework.expression.ParseException;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

public class SpelMatcher<T> extends ArgumentMatcher<T>{
    private final String spel;
    private final Object[] args;
    private static final String ARG_PREFIX = "a";
    public SpelMatcher(String spel, Object… args) {
        this.spel = spel;
        this.args = args;
    }

    @Override
    public boolean matches(Object argument) {
        SpelExpressionParser p = new SpelExpressionParser();
        StandardEvaluationContext ctx = new StandardEvaluationContext();
        ctx.setRootObject(argument);
        for(int i=0; i<args.length; i++) {
            ctx.setVariable(ARG_PREFIX+(i+1), args[i]);
        }
        try {
            Expression exp = p.parseExpression(spel);
            return (Boolean)exp.getValue(ctx);
        } catch (ParseException e) {
            throw new IllegalArgumentException(e);
        } catch (EvaluationException e) {
            throw new IllegalArgumentException(e);
        }
    }
    public static <T> T argel(String spel, Object… args) {
        return  Matchers.<T>argThat(new SpelMatcher<T>(spel, args));
    }
    public static <T> Matcher<T> spel(String spel, Object… args) {
        return new SpelMatcher<T>(spel, args);
    }
}

 

사용방법은 간단하다.

argThat과 함께 SpelMatcher 인스턴스를 만들어서 사용하던가 아니면 간단하게 만들어둔 스태틱 메소드를 사용하면 된다.

argel은 Mockito의 ArgumentMatcher이고 spel은 Hamcrest의 Matcher이다.

다음과 같은 도메인 오브젝트가 있다고 하고.

class User {
        String name;
        int age;
        double saving;
        String[] nicks;
        User nested;

       // getters, setters

}

다음과 같이 초기화 시켰다면,

User user = new User("Toby", 30, 123.45, new String[] {"A","B","C"});
User userNested = new User("Mich", 10, 234.56, new String[] {"1","2","3"});
user.setNested(userNested);

 

다음과 같이 사용이 가능하다.

assertThat(user, spel("name == #a1", "Toby"));

첫번째 파라미터는 SpEL이고, 그 후로는 #a로 시작하는 변수에 바인딩할 파라미터들이다. varargs이므로 갯수에는 제한이 없다. spel에서는 user를 rootObject로 설정하고 시작한다. 따라서 name이라고 하면 user.name이 되는 것이다. 당연히 user.getName()이 호출될 것이고. #a1이면 첫번째 바인딩 파라미터를 사용한다. 그 뒤로 붙으면 계속 번호가 늘어나면 된다.

Mockito에서 사용한다면 이렇게 쓸 수 있다.

verify(collabor).add((User)argel("name == #a1", "Toby"));

SpEL과 바인딩 파라메터만 넘기기 때문에 Generics로 리턴타입을 캐스팅하기가 어려웠다. 타입추론을 적용하려고 했지만, 왜그런지 add() 메소드의 컨텍스트를 이용한 타입추론은 성공을 못했다. 결국 직접 캐스팅 하거나 아니면 타입 파라미터를 줘야 한다. 타입 파라미터는 스태틱 임포트된 메소드에는 또 사용이 불가능하다. 결국 클래스이름부터 줘야 한다.

verify(collabor).add(SpelMatcher.<User>argel("name == #a1", "Toby"));

재밌는 것은 같은 내용인데도 할당문을 거쳐서 사용하면 캐스팅이 필요없고 타입추론이 잘 먹는다는 점이다.

User u = argel("name == #a1", "Toby");
verify(collabor).add(u);

전형적인 타입추론 케이스인 리턴타입에도 Generics 스타일을 쓰는(Matcher<T>) spel에서는 잘 되는데, 메소드 컨텍스트에서 T타입으로 리턴하는 경우에는 안되는 것이.. 뭔가 아쉬움이다. 다음 자바 버전에서는 될지도.

 

어쨌든 SpEL의 막강한 기능을 이용해서 다양한 검증이 가능하다.

어레이나, 리스트, 맵도 지원하고 당연히 중첩된 오브젝트 그래프를 따르는 네비게이션도 된다. 복합조건도 당연히 잘 되고. 다음은 테스트 코드에서 확인해봤던 것들의 일부이다.

nicks[0] == ‘A’
age > 29 and age < 31
nicks.length == 3
name == ‘Toby’ and nested.nicks[0] == ’1′
"name == #a1 and age == #a2", "Toby", 30
"saving == #a1 and nicks[0] == #a2", 123.45, "A"

 

SpEL은 메소드 호출도 가능하다.

연산자도 재정의 할 수가 있고, 이런 저런 확장기능도 뛰어나다.

 

아무튼 이제 Mockito 사용시 귀찮은 커스톰 ArgumentMatcher 정의는 이제 그만. 참 JUnit assertThat 사용할 때도.

스프링 3.0 M3 버전 이상의 expression 모듈이 있어야 바르게 동작할 것이다. expression 모듈은 다른 의존관계가 없으니 아마 spring2.5에도 가져가 사용할 수도 있을 듯.

 

SpEL은 지난번 @Check를 이용한 익셉션의 메시지까지 확인하는 테스트기능 이후로 두번째 적용해봤는데, 응용가능성이 무한하다는 느낌이다. 다만, 텍스트 기반의 런타임 파싱구조이므로 리팩토링에 살짝 취약하다는게 단점.

Related posts:

  1. Spring 3.0 EL (Spel)을 이용한 AssertThrows 확장 (3)
  2. Spring 3.0 EL (Spel)을 이용한 AssertThrows 확장 (2)
  3. Spring 3.0 (59) 프로퍼티 파일 이용하기 – placeholder vs SpEL
  4. Spring 3.0 EL (Spel)을 이용한 AssertThrows 확장 (1)
  5. Spring 3.0 @MVC 메소드에서 자동으로 리턴 모델에 추가되는 것들
  6. Spring 3.0 (26) Spring Expression Language와 @Value
  7. Spring 3.0 (2) R-518 스프링의 새 모듈 OXM(Object/XML Mapping)
  8. Spring ROO 대충대충 분석 (3) ROO의 Inter-type declaration
  9. 테스트 코드에서 static import를 편하게 넣는 방법
  10. Spring기반의 Hibernate DAO Unit Test 만들기
  11. 테스트 할 수 없는 것을 테스트 하기. Spring ROO와 static method mocking.
  12. [토스3] 매핑 가능한 BeanPropertySqlParameterSource
  13. Spring 3.0 (46) Spring 3.0 M4 릴리스
  14. 미리 보는 Spring 3.0.1의 변경사항
  15. Spring 상식퀴즈 (1) – DI 태클하기

Facebook comments:

to “Spring Expressions(SpEL)를 이용한 Mockito Argument Matcher 만들기”

  1. 생각하는게 다 비슷한가봅니다. 저도 이런 걸 찾다가 결국 matcher 코드 생성기를 만들어 쓰고 있습니다.
    mockito 에 ArgumentMatcher 라는게 있었군요. describeTo 구현하느라 완전 삽질했는데…

  2. 초보/ 코드생성기라고 하시니 또 한가지 아이디어가 또오르는군요. 자바코드는 아니고 바이트코드 생성방식을 이용해서 다이나믹하게 Matcher를 만들어주는 방법도 한번 시도해봐야겠습니다. 복잡한 조건은 힘들지만 equals()와 and비교정도라면 가능할 것 같군요.

  3. 글보고 감동먹고 있었는데, Mockito 이번 1.8 릴리스에 argument를 저장해놓고 나중에 assert할 수 있도록 해주는 기능이 들어갔네요. EasyMock에는 Capture라고 예전부터 있었던 것.
    그럼에도 빛이 바라지 않는 멋진 팁 감사~!

  4. 권남/ argument 저장 후 나중에 검증할 수 있도록 하는 방식이라면, 직접 mock을 만들어서 썼을 때와 비슷한 방법으로 사용이 가능하겠네요. 멋진데요.

  5. PBg7Vq krdyyqljwzes, [url=http://ahurpbmhtxub.com/]ahurpbmhtxub[/url], [link=http://kaouwvycihef.com/]kaouwvycihef[/link], http://wlgxeuwtsvnj.com/

  6. I came to your “Spring Expressions(SpEL)를 이용한 Mockito Argument Matcher 만들기 » Toby&” page and noticed you could have a lot more traffic. I have found that the key to running a website is making sure the visitors you are getting are interested in your subject matter. There is a company that you can get traffic from and they let you try it for free. I managed to get over 300 targetted visitors to day to my website. Visit them today: http://bag.sh/16M

  7. I had been honored to get a call from a friend immediately he identified the important recommendations shared in your site. Going through your blog posting is a real amazing experience. Thanks again for considering readers just like me, and I wish you the best of success being a professional topic.

  8. gucci belt cheap prices Spring Expressions(SpEL)를 이용한 Mockito Argument Matcher 만들기 » Toby’s Epril

  9. gucci eyeglasses 2010 Spring Expressions(SpEL)를 이용한 Mockito Argument Matcher 만들기 » Toby’s Epril

  10. womens adidas shoes Spring Expressions(SpEL)를 이용한 Mockito Argument Matcher 만들기 » Toby’s Epril

  11. best men’s shoes Spring Expressions(SpEL)를 이용한 Mockito Argument Matcher 만들기 » Toby’s Epril

  12. free shipping nike shoes Spring Expressions(SpEL)를 이용한 Mockito Argument Matcher 만들기 » Toby’s Epril

  13. mbt fora shoes Spring Expressions(SpEL)를 이용한 Mockito Argument Matcher 만들기 » Toby’s Epril

  14. Viagra generika
    Work with incorporating extra Vit C in your daily diet or through dietary supplement tablets as a way to improve your immunities. A number of fresh fruits like citrus many fruits and strawberries contain vitamin C. If you choose to use vit c health supplements, they may be obtained at most of the nutrition stores and size marketers.
    viagra online
    Are you looking for recommendations on taking care of your mouth area, teeth and gums? If so, you might have appear to the right location. Handling your oral cavity is very important and also the post that follows will show you how. Continue reading to discover the very best oral health suggestions available.
    viagra gĂĽnstig kaufen
    To conclude, not everyone is satisfied with the way they look. One way that people alter this is certainly by obtaining surgical treatment accomplished. The surgical procedures can various results, according to the operating specialist, in addition to their expertise. Maintain the previously mentioned tips under consideration, just before getting surgical treatment carried out, to get the best results imaginable.Helpful Information When Picking Cosmetic Surgery Methods
    kamagra gel

  15. viagra belgique
    Keep track of your finances and help save statements for two weeks. This can help you decide in which your cash goes and where you may commence reducing bills. You will certainly be astonished at what you spend and where you may cut costs. Make use of this instrument to develop a financial budget.
    Viagra generika
    From learning how to regulate your diet program to finding out the correct types of exercise routines that can be done to keep your blood sugar levels correctly well-balanced, you will have the ability to are living a typical and successful lifestyle in case you have diabetes mellitus. The following will help encourage and embolden one to improve your health.
    cialis prix
    Search for the Hatha Yoga exercise Sunshine Salutation on the internet for a number of gentle, simple expands you could carry out each morning and every night to bolster your again and increase your spine. Executing this mild combination of exercises for a quarter-hour, 2 times a day could work miracles to get rid of your back pain.
    kamagra suisse

  16. cialis pris
    Although it is much more essential to buy an extremely profitable business than the usual organization which includes excellent management, you ought to watch out for snakes. Even businesses that are exceedingly successful presently can be poor investments if very terrible management is in manage. In the event you discover a enterprise with management techniques which make you leery, then refrain.
    cialis pris
    Visit your nearby financial institution and get pre-approved for a auto loan. This particular one stage cannot only help you save a lot of time at dealership, but it will save you money most of the time. By permitting that loan on your financial institution, you may work out your monthly interest more efficiently hence, cutting your general transaction.
    viagra comprar
    Among the best strategies to get rid of snoring throughout the night is to reduce on your consumption of alcoholic beverages through the day. Liquor has a tendency to firm up your airways, that will make it more difficult to inhale when you visit mattress. Lower your drinking and sleep inside a relaxing manner.
    levitra suisse

  17. cialis fass
    Prior to struck the bedding at night, you should think about all of the fantastic things which is taking place in your life right now. Do the same thing the following early morning. You might assume that you do not have a bit of good stuff happening in your life, but each man or woman can discover some thing excellent in his / her life, even if it is anything really small. Doing so will help you to decrease your anxiousness.
    priligy fass
    Be aware of the simple distinctions involving irritants and allergens. Contact with an allergen provokes a physical effect in the body responding to an unnatural protein. Irritants include things like paper dust, compound gases, scent and tobacco smoke. These elements are irksome, nevertheless they tend not to hold a genuine health risks, more often than not.
    cialis schweiz
    Blogging is a great illustration of social media marketing. Be sure that you benefit from possessing a blog site to showcase your services and products to buyers. Article on a regular basis on your blog so you can get exciting information out around the world, but additionally to point out to people who you exist and so does your blog site. Individuals tend to just forget about blogs that aren’t often up to date as they get bored and move ahead.
    Cialis lilly

  18. kamagra oral jerry
    If you’re worried your newly colored nails will smear, you can protect them with a slim film of some form of oils. Sometimes put a decline of essential olive oil on your own palm and massage it across the fingernails or toenails, as well as simpler, make use of a can of essential olive oil preparing food apply and give every finger simply the quickest effect of food preparation spray. The oils will kind a defensive shield that will keep your polish from smearing.
    priligy kopen
    Work with people to assist you. You may believe that because you’re a home business, you must do everything all on your own and that’s not so. There are actually amount of locations that you could find qualified, affordable aid for whatever you decide to need to have done. Permitting others take care of several things frees you up to focus on whatever you absolutely appreciate.
    priligy österreich
    Have you been fed up with your allergies making you feel just awful? Are you also tired with your allergic reactions trying to keep from performing stuff you enjoy? Properly, you need to understand that there are stuff that you can do that can easily make a variation. Make time to see the pursuing report to obtain some good suggestions.
    cialis fass

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