Skip to content

Commit e79dc5a

Browse files
committed
Improve test coverage
Fix all issues uncovered by tests.
1 parent 426f337 commit e79dc5a

12 files changed

+795
-78
lines changed

application.go

+5-9
Original file line numberDiff line numberDiff line change
@@ -148,12 +148,8 @@ func (app *Application) NewHTTPRouterHandle(resName, actName string, h Handler)
148148
// Build context
149149
gctx, cancel := context.WithCancel(context.Background())
150150
defer cancel() // Signal completion of request to any child goroutine
151-
gctx = context.WithValue(context.Background(), reqKey, r)
152-
gctx = context.WithValue(gctx, respKey, w)
153-
gctx = context.WithValue(gctx, paramKey, params)
154-
gctx = context.WithValue(gctx, queryKey, query)
155-
gctx = context.WithValue(gctx, payloadKey, payload)
156-
ctx := &Context{Context: gctx, Logger: logger}
151+
ctx := NewContext(gctx, r, w, params, query, payload)
152+
ctx.Logger = logger
157153

158154
// Handle invalid payload
159155
handler := middleware
@@ -183,21 +179,21 @@ func (app *Application) NewHTTPRouterHandle(resName, actName string, h Handler)
183179
func DefaultErrorHandler(c *Context, e error) {
184180
status := 500
185181
if _, ok := e.(*support.BadRequestError); ok {
186-
c.ResponseHeader().Set("Content-Type", "application/json")
182+
c.Header().Set("Content-Type", "application/json")
187183
status = 400
188184
}
189185
if err := c.Respond(status, []byte(e.Error())); err != nil {
190186
Log.Error("failed to send default error handler response", "err", err)
191187
}
192188
}
193189

194-
// terseerrorhandler behaves like defaulterrorhandler except that it does not set the response
190+
// TerseErrorHandler behaves like DefaultErrorHandler except that it does not set the response
195191
// body for internal errors.
196192
func TerseErrorHandler(c *Context, e error) {
197193
status := 500
198194
var body []byte
199195
if _, ok := e.(*support.BadRequestError); ok {
200-
c.ResponseHeader().Set("Content-Type", "application/json")
196+
c.Header().Set("Content-Type", "application/json")
201197
status = 400
202198
body = []byte(e.Error())
203199
}

application_test.go

+222
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
package goa_test
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
7+
"github.com/julienschmidt/httprouter"
8+
. "github.com/onsi/ginkgo"
9+
. "github.com/onsi/gomega"
10+
"github.com/raphael/goa"
11+
)
12+
13+
var _ = Describe("Application", func() {
14+
const appName = "foo"
15+
var app *goa.Application
16+
17+
BeforeEach(func() {
18+
app = goa.New(appName)
19+
})
20+
21+
Describe("New", func() {
22+
It("creates an application", func() {
23+
Ω(app).ShouldNot(BeNil())
24+
})
25+
26+
It("initializes the application fields", func() {
27+
Ω(app.Name).Should(Equal(appName))
28+
Ω(app.Logger).ShouldNot(BeNil())
29+
Ω(app.ErrorHandler).ShouldNot(BeNil())
30+
Ω(app.Router).ShouldNot(BeNil())
31+
})
32+
})
33+
34+
Describe("Use", func() {
35+
Context("with a valid middleware", func() {
36+
var m goa.Middleware
37+
38+
BeforeEach(func() {
39+
m = goa.RequestID()
40+
})
41+
42+
JustBeforeEach(func() {
43+
app.Use(m)
44+
})
45+
46+
It("adds the middleware", func() {
47+
Ω(app.Middleware).Should(HaveLen(1))
48+
Ω(app.Middleware[0]).Should(BeAssignableToTypeOf(goa.RequestID()))
49+
})
50+
})
51+
})
52+
53+
Describe("NewHTTPRouterHandle", func() {
54+
const resName = "res"
55+
const actName = "act"
56+
var handler goa.Handler
57+
const respStatus = 200
58+
var respContent = []byte("response")
59+
60+
var httpHandle httprouter.Handle
61+
var ctx *goa.Context
62+
63+
JustBeforeEach(func() {
64+
httpHandle = app.NewHTTPRouterHandle(resName, actName, handler)
65+
})
66+
67+
BeforeEach(func() {
68+
handler = func(c *goa.Context) error {
69+
ctx = c
70+
c.Respond(respStatus, respContent)
71+
return nil
72+
}
73+
})
74+
75+
It("creates a handle", func() {
76+
Ω(httpHandle).ShouldNot(BeNil())
77+
})
78+
79+
Context("with a request", func() {
80+
var rw http.ResponseWriter
81+
var r *http.Request
82+
var p httprouter.Params
83+
84+
BeforeEach(func() {
85+
var err error
86+
r, err = http.NewRequest("GET", "/foo", nil)
87+
Ω(err).ShouldNot(HaveOccurred())
88+
rw = new(TestResponseWriter)
89+
id := httprouter.Param{Key: "id", Value: "42"}
90+
query := httprouter.Param{Key: "sort", Value: "asc"}
91+
p = httprouter.Params{id, query}
92+
})
93+
94+
JustBeforeEach(func() {
95+
httpHandle(rw, r, p)
96+
})
97+
98+
It("creates a handle that handles the request", func() {
99+
i, ok := ctx.Get("id")
100+
Ω(ok).Should(BeTrue())
101+
Ω(i).Should(Equal("42"))
102+
s, ok := ctx.Get("sort")
103+
Ω(ok).Should(BeTrue())
104+
Ω(s).Should(Equal("asc"))
105+
tw := rw.(*TestResponseWriter)
106+
Ω(tw.Status).Should(Equal(respStatus))
107+
Ω(tw.Body).Should(Equal(respContent))
108+
})
109+
110+
Context("and middleware", func() {
111+
middlewareCalled := false
112+
113+
BeforeEach(func() {
114+
app.Use(TMiddleware(&middlewareCalled))
115+
})
116+
117+
It("calls the middleware", func() {
118+
Ω(middlewareCalled).Should(BeTrue())
119+
})
120+
})
121+
122+
Context("and a middleware chain", func() {
123+
middlewareCalled := false
124+
secondCalled := false
125+
126+
BeforeEach(func() {
127+
app.Use(TMiddleware(&middlewareCalled))
128+
app.Use(SecondMiddleware(&middlewareCalled, &secondCalled))
129+
})
130+
131+
It("calls the middleware in the right order", func() {
132+
Ω(middlewareCalled).Should(BeTrue())
133+
Ω(secondCalled).Should(BeTrue())
134+
})
135+
})
136+
137+
Context("with a handler that fails", func() {
138+
errorHandlerCalled := false
139+
var oldErrorHandler goa.ErrorHandler
140+
141+
BeforeEach(func() {
142+
oldErrorHandler = app.ErrorHandler
143+
app.SetErrorHandler(TErrorHandler(&errorHandlerCalled))
144+
})
145+
146+
AfterEach(func() {
147+
app.SetErrorHandler(oldErrorHandler)
148+
})
149+
150+
Context("by returning an error", func() {
151+
BeforeEach(func() {
152+
handler = func(ctx *goa.Context) error {
153+
return fmt.Errorf("boom")
154+
}
155+
})
156+
157+
It("triggers the error handler", func() {
158+
Ω(errorHandlerCalled).Should(BeTrue())
159+
})
160+
})
161+
162+
Context("by not handling the request", func() {
163+
BeforeEach(func() {
164+
handler = func(ctx *goa.Context) error {
165+
return nil
166+
}
167+
})
168+
169+
It("triggers the error handler", func() {
170+
Ω(errorHandlerCalled).Should(BeTrue())
171+
})
172+
})
173+
})
174+
})
175+
})
176+
})
177+
178+
func TErrorHandler(witness *bool) goa.ErrorHandler {
179+
return func(ctx *goa.Context, err error) {
180+
*witness = true
181+
}
182+
}
183+
184+
func TMiddleware(witness *bool) goa.Middleware {
185+
return func(h goa.Handler) goa.Handler {
186+
return func(ctx *goa.Context) error {
187+
*witness = true
188+
return h(ctx)
189+
}
190+
}
191+
}
192+
193+
func SecondMiddleware(witness1, witness2 *bool) goa.Middleware {
194+
return func(h goa.Handler) goa.Handler {
195+
return func(ctx *goa.Context) error {
196+
if !*witness1 {
197+
panic("middleware called in wrong order")
198+
}
199+
*witness2 = true
200+
return h(ctx)
201+
}
202+
}
203+
}
204+
205+
type TestResponseWriter struct {
206+
ParentHeader http.Header
207+
Body []byte
208+
Status int
209+
}
210+
211+
func (t *TestResponseWriter) Header() http.Header {
212+
return t.ParentHeader
213+
}
214+
215+
func (t *TestResponseWriter) Write(b []byte) (int, error) {
216+
t.Body = append(t.Body, b...)
217+
return len(b), nil
218+
}
219+
220+
func (t *TestResponseWriter) WriteHeader(s int) {
221+
t.Status = s
222+
}

codegen/gen_app/generator_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ func (ctx *GetWidgetContext) OK(resp ID) error {
250250
if err != nil {
251251
return fmt.Errorf("invalid response: %s", err)
252252
}
253-
ctx.ResponseHeader().Set("Content-Type", "vnd.rightscale.codegen.test.widgets; charset=utf-8")
253+
ctx.Header().Set("Content-Type", "vnd.rightscale.codegen.test.widgets; charset=utf-8")
254254
return ctx.JSON(200, r)
255255
}
256256
`

codegen/gen_app/writers.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,7 @@ func (ctx *{{$ctx.Name}}) {{goify .Name true}}({{$mt := (index $ctx.MediaTypes .
397397
if err != nil {
398398
return fmt.Errorf("invalid response: %s", err)
399399
}
400-
ctx.ResponseHeader().Set("Content-Type", "{{$mt.Identifier}}; charset=utf-8")
400+
ctx.Header().Set("Content-Type", "{{$mt.Identifier}}; charset=utf-8")
401401
return ctx.JSON({{.Status}}, r){{else}}return ctx.Respond({{.Status}}, nil){{end}}
402402
}
403403
{{end}}`

0 commit comments

Comments
 (0)