testing
테스트를 하다가 ByteArrayInputStream 관련 에러를 만남
/a/b/c
로의 요청을 했을 때에는 json 으로 응답이 잘 오는데 ring의 mock을 써서 응답을 받으면 ByteArrayInputStream으로 오는 상황
#응답 예
:body #object[java.io.ByteArrayInputStream 0x56fae55c java.io.ByteArrayInputStream@56fae55c]
응답 크기가 영향을 줄 수 있을까?
검색 결과 를 보면 그럴 수도.
ByteArrayInputStream 클래스는 바이트 배열을 차례로 읽어들이는 클래스
ByteArrayOutputStream 클래스는 내부 저장공간에 바이트 배열을 저장하는 클래스
ByteArrayOutputStream의 toByteArray()메소드를 통해 저장공간에 있는 내용을 얻을 수 있다.
JVM이 다루는 힙 메모리 사이즈 보다 큰 배열을 사용할 수 없다.
테스트를 실수해서 크기가 영향을 받은 것 처럼 보였다...
mock의 결과가 json인데...
당연히 clojure map이라고 착각했다.
바보이미 app의 리턴으로 json이 나왔을 텐데 map이라고 착각하고 열어보려고 한 죄.
내가 비교할 결과를 json-body로 싸거나, (json으로 나온)결과를 map으로 바꾸거나, 모델의 test 를 만들자
;; json으로 나온 결과를 map으로 파싱하는 방법
(parse-string (slurp (:body response)) true)
결론
디버그 환경을 좀더 구축하자.
어차피 현재는 핸들러 테스트를 하려는 것이지, 로직 테스트는 아니기 때문에 json body를 고치는 것보다 모델의 테스트를 만드는 걸로.
결국은 ByteArrayInputStream과는 상관없는 이야기가 되어버렸다. 해당 에러를 보면 내가 어떤 포맷을 보려고 했는지 잘 생각해보자.
\n
과 \\n
(문자열 escape) : 테스트 mocking을 하다 생긴일
\n
과 \\n
(문자열 escape) : 테스트 mocking을 하다 생긴일api개발시 swagger 나 postman 등의 클라이언트request에는
abc\nd
으로 보내는 것이 test나 clojure 코드 내에서는abc\\nd
로 만들어야 같은 문자열로 인식한다.escape 문제라는 것은 알겠는데, 계속 헷갈리기에
clojure.string/split
함수를 보며 간단히 정리해보자.
;; 주의할 점 : 단순히 문자열 \ㅜㅜㅜㅜn을 찾아서 자른 것이 아니다, escape가 동작한 것이다.
(require '[clojure.string :as str])
(def s "a\nbb\\ncccc\\\nd")
(str/split s #"\n")
;; => ["a" "bb\\ncccc\\" "d"]
;; \를 보고 escape 했기 때문에 논리적으로, 공백문자 (\n)를 기준으로 자른 것, 만약 문자열그대로 raw값이라고 판단했다면, bb\rhk cccc도 분리가 되었어야 한다.
(str/split s #"\\n")
;; => ["a\nbb" "cccc\\\nd"]
;; 마찬가지 이유로 문자열 \과 공백문자를 합쳐서 찾아 자른 것이다. cccc 와 d는 왜 분리가 안되었냐면, 역슬래시가 한번 더 escape되었기 때문이다.
(str/split s #"\\\n")
;; => ["a\nbb\\ncccc" "d"]
;; escape가 아닌 역슬래시와 공백을 찾아서 자른 것
(str/split s #"\\\\n")
;; => ["a\nbb\\ncccc\\\nd"]
;; 처음부터 여기 매칭되는 것은 없었다.
여담
내가 클로저를 사용하면서
(def temp "aaa\n")
와 같이 바인딩을 할 때, escape문자를 쓰지 않고 "aaa\n" 자체를 raw 값으로 바인딩하고 싶지만, 그럴 순 없다. 다른 언어도 대부분 마찬가지 일 것이다. 애초에 string 객체를 만들 때 escape 할테니까.https://clojuredocs.org/clojure.string/escape 이런 것도 있지만, 여기선 진짜 문자열 변환이니까 또 다른 문제이다.
요청/응답 처리를 할 때, 정신을 똑바로 차리자.
slurp, stream : test 중에 값을 꺼내다가 생긴 일
(let [body (parse-string (slurp (:body response)) true)]
(println body)
(println (slurp (:body response))))
두개의 print 결과물을 기대했는데, 첫번째 body만 출력된다. 음?
response 가 stream이고 https://clojuredocs.org/clojure.java.io/input-stream, slurp로 한번 빨아들였기 (?) 때문에, 두번째 slurp에서는 동작하지 않은 것, 값이 여러번 필요할 때는 let으로 적절히 바인딩해서 쓰자.
Last updated