Slava Akhmechet wrote:
I'm building a web framework on top of Hunchentoot and I ran into problems while trying to unit test some of my code. Essentially I need to unit test behavior that happens accross requests. I want to do it without starting Hunchentoot by faking the necessary objects (request, session, etc.)
I had a similar problem, and I guess my not very elegant solution was to create a dummy-request class, which basically has the same slots as that of hunchentoot::request, and you can set parameters like so, and set the dummy request instance to *request*:
(defclass dummy-request () ((headers-in :initarg :headers-in :initform nil) (method :initarg :method) (uri :initarg :uri) (server-protocol :initarg :server-protocol) (content-stream :initarg :content-stream :reader content-stream) (cookies-in :initform nil) (get-parameters :initform nil) (post-parameters :initform nil) (script-name :initform nil) (query-string :initform nil) (session :initform nil :accessor hunchentoot::session) (aux-data :initform nil :accessor hunchentoot::aux-data) (raw-post-data :initform nil)))
And then:
(let ((*request* (make-instance 'dummy-request))) (setf (slot-value *request* 'method) :post) (setf (slot-value *request* 'post-parameters) '(("id" . "10") ("name" . "Chicago")))
And you can access this in the regular way:
(setf some-var (get-parameter "id"))
I found out that setting some vars like hunchentoot::*session-secret* properly and doing a start-session lets you use session within a test happily. For most tests that use session/request related code, I do something like this and put it in a macro:
(let* ((hunchentoot::*remote-host* "localhost") (hunchentoot::*session-secret* (hunchentoot::reset-session-secret)) (hunchentoot::*reply* (make-instance 'hunchentoot::reply)) (*request* (make-instance 'dummy-request)) (*session* (start-session)))
I'm not sure if this is the best way to do this, but this approach works fine for me.
HTH, Vamsee.