최근(?) 자바스크립트에서는 모듈 패턴(Module Pattern)을 많이 사용한다.
이렇게 많이 사용하는 이유는 개인적으로 AMD의 영향이 크지 않을까 생각한다. (AMD의 좀 안좋은 인식이 있는데 이건 나중에 시간이 되면 쓰도록 하고....)
뭐.. 어쨌건 모듈 패턴을 사용하는 이유야 다양하겠지만 대부분은 지금의 자바스크립트에서 지원하지 않는 private 속성을 사용하기 위함이 큰 것 같다.(ECMA6에서는 뭐가 있는것 같은데..)
나는 사실 모듈 패턴을 선호하지 않는 편이다. 그 이유 중 하나가 코드 리딩이 힘들다.
왜냐하면 모듈 패턴은 함수로 감싼 형식이라 구현부를 볼 때 함수의 파라메터가 있다면 제일 마지막 부분을 확인해야 알 수 있고 클로져를 생각보다 많이 사용해 코드 리딩도 좀 힘들다. 그래서 난 개인적으로 모듈 패턴을 사용할 때는 파라메터를 넣지 않기를 선호하며 클로져도 적게 쓰려고 한다.
그리고 모듈 패턴을 쓰면 private의 사용이 많아지고 private이 많아질 수록 테스트는 만들기 힘들어진다. 물론, private를 테스트하기 힘든건 모듈 패턴의 문제는 아니다.
이런 경우 대체적으로 private함수는 직접 테스트하기 보다는 private함수를 사용하는 public함수를 테스트한다.
나도 보통은 그렇게 하는데 한편으론 맘에 안들때도 있다.
예를 들면 아래의 코드형식이다.
(function(){
var global = this;
function Stub(vName, sType){
this.stubMethod = new StubMethod();
}
Stub.prototype.with_param = function(){
return this.stubMethod;
}
//private
function StubMethod(iStub){
}
StubMethod.prototype.and_return = function(vReturn){
}
global.stub = global.Stub = Stub;
})();
위에 코드를 보면 StubMethod는 외부에서 생성해서 사용하지 않기 때문에 외부에 노출하지 않는다.
그리고 with_param의 반환 값이 StubMethod인지 테스트해야 하는 코드를 아래와 같이 작성하려고 한다.
test("with_param의 반환 값은 StubMethod 인스턴스여야 한다.",function(){
//Given
var stubInstance = stub("Stub");
//When
var stubMethod = stubInstance.with_param();
//Then
ok(stubMethod instanceof StubMethod);
});
근데 여기서 StubMethod는 외부에 노출하지 않았기 때문에 위와 같은 테스트가 불가능하다.
그래서 테스트하는 방법을 고민해봤는데 몇 가지가 떠올랐다.
첫 번째. 반환 값을 가지고 add_return을 사용하여 테스트한다.(간접적으로),
두 번째. 반환 값에서 add_return메서드가 있는지 확인하는 테스트를 작성해야 한다(덕타이핑과 같이).
세 번째. 키워드를 넘겨서 테스트 중이면 외부에서도 StubMethod를 접근할 수 있게 한다. (이건 좀 구린것 같다.)
처음 고민한건 add_return 함수의 기능을 테스트하면 StubMethod인지 동시에 테스트되는 방법이다. 물론 간접적으로 테스트 되지만 반환 값이 StubMethod인지 테스트하는 부분이 코드로 표현되지 않아서 좀 별루라고 생각했다.
이것 저것 고민하다가 결국엔 덕타이핑으로 판단했지만 여전히 찜찜함은 남는다.
test("with_param은 반환 값이 StubMethod 인스턴스여야 한다.",function(){
//Given
var stubInstance = stub("Stub");
//When
var stubMethod = stubInstance.with_param();
//Then
// ok(stubMethod instanceof StubMethod);
// StubMethod는 private으로 접근할 수 없어 덕타이핑으로 판단한다.
equal(typeof stubMethod.and_return,"function");
});
이와 관련한 질문도 많고 답변도 봤는데 나의 고민을 해결해주는 글은 없었다. 그리고 유사한 패턴이 jQuery의 Deferred, Promise인 것 같아서 코드와 테스트 케이스를 보니 위에 경우랑은 좀 차이가 있었다.
결론은 위와 같이 했지만 이런 경우는 어떻게 처리해야 할지 아직 고민이 된다.
ps. 여전히 고민인 건 정말 private로 만들어야만 했는가? 그냥 public이면 되는거 아닌가? 외부에 노출시켜 발생하는 문제에 비해 테스트의 가치가 큰게 아닌가? 등 많은 고민이 되는데 잘 모르겠다.
ps. 정말 오랫만에 블로그를 썼다. 한동안 바쁘다는 이유로 안썼는데 이젠 조금씩 써보려고 하는데 얼마나 갈지는 잘 모르겠다. ㅎㅎ