@@ -2,25 +2,35 @@ package main
22
33import (
44 "bytes"
5+ "context"
6+ "encoding/json"
57 "fmt"
8+ "gofr.dev/pkg/gofr/testutil"
69 "net/http"
10+ "net/http/httptest"
711 "os"
812 "testing"
913 "time"
1014
1115 "github.com/stretchr/testify/assert"
1216 "github.com/stretchr/testify/require"
17+ "go.uber.org/mock/gomock"
1318
14- "gofr.dev/pkg/gofr/testutil"
19+ "gofr.dev/pkg/gofr"
20+ "gofr.dev/pkg/gofr/container"
21+ "gofr.dev/pkg/gofr/logging"
1522)
1623
1724func TestMain (m * testing.M ) {
1825 os .Setenv ("GOFR_TELEMETRY" , "false" )
1926 m .Run ()
2027}
2128
22- func TestExamplePublisher (t * testing.T ) {
29+ func TestExamplePublisherError (t * testing.T ) {
30+ t .Setenv ("PUBSUB_BROKER" , "localhost:1092" )
31+
2332 configs := testutil .NewServerConfigs (t )
33+ host := fmt .Sprint ("http://localhost:" , configs .HTTPPort )
2434
2535 go main ()
2636 time .Sleep (200 * time .Millisecond )
@@ -30,88 +40,117 @@ func TestExamplePublisher(t *testing.T) {
3040 path string
3141 body []byte
3242 expectedStatusCode int
33- expectedError error
3443 }{
35- {
36- desc : "valid order" ,
37- path : "/publish-order" ,
38- body : []byte (`{"data":{"orderId":"123","status":"pending"}}` ),
39- expectedStatusCode : http .StatusCreated ,
40- },
41- {
42- desc : "invalid order" ,
43- path : "/publish-order" ,
44- body : []byte (`{"data":,"status":"pending"}` ),
45- expectedStatusCode : http .StatusInternalServerError ,
46- },
47- {
48- desc : "valid product" ,
49- path : "/publish-product" ,
50- body : []byte (`{"data":{"productId":"123","price":"599"}}` ),
51- expectedStatusCode : http .StatusCreated ,
52- },
53- {
54- desc : "invalid product" ,
55- path : "/publish-product" ,
56- body : []byte (`{"data":,"price":"pending"}` ),
57- expectedStatusCode : http .StatusInternalServerError ,
58- },
44+ {"valid order" , "/publish-order" , []byte (`{"data":{"orderId":"123","status":"pending"}}` ), http .StatusInternalServerError },
45+ {"valid product" , "/publish-product" , []byte (`{"data":{"productId":"123","price":"599"}}` ), http .StatusInternalServerError },
5946 }
6047
61- c := http.Client {}
48+ client := http.Client {}
6249
6350 for i , tc := range testCases {
64- req , _ := http .NewRequest (http .MethodPost , configs . HTTPHost + tc .path , bytes .NewBuffer (tc .body ))
51+ req , _ := http .NewRequest (http .MethodPost , host + tc .path , bytes .NewBuffer (tc .body ))
6552 req .Header .Set ("content-type" , "application/json" )
66- resp , err := c .Do (req )
53+
54+ resp , err := client .Do (req )
55+ require .NoError (t , err , "TEST[%d] %s failed" , i , tc .desc )
6756 defer resp .Body .Close ()
6857
69- assert .Equal (t , tc .expectedStatusCode , resp .StatusCode , "TEST[%d], Failed.\n %s" , i , tc .desc )
70- require .NoError (t , err , "TEST[%d], Failed.\n %s" , i , tc .desc )
58+ assert .Equal (t , tc .expectedStatusCode , resp .StatusCode , "TEST[%d] %s failed" , i , tc .desc )
7159 }
7260}
7361
74- func TestExamplePublisherError (t * testing.T ) {
75- t .Setenv ("PUBSUB_BROKER" , "localhost:1012" )
62+ func TestOrderFunction (t * testing.T ) {
63+ ctrl := gomock .NewController (t )
64+ defer ctrl .Finish ()
7665
77- configs := testutil .NewServerConfigs (t )
66+ tests := []struct {
67+ name string
68+ body string
69+ expectError bool
70+ publishError error
71+ expectedResult interface {}
72+ }{
73+ {"valid order" , `{"orderId":"123","status":"pending"}` , false , nil , "Published" },
74+ {"invalid JSON" , `{"orderId":,"status":"pending"}` , true , nil , nil },
75+ {"publish error" , `{"orderId":"123","status":"pending"}` , true , fmt .Errorf ("publish failed" ), nil },
76+ }
7877
79- host := fmt .Sprint ("http://localhost:" , configs .HTTPPort )
78+ for _ , tt := range tests {
79+ t .Run (tt .name , func (t * testing.T ) {
80+ mockContainer , mocks := container .NewMockContainer (t )
8081
81- go main ()
82- time .Sleep (200 * time .Millisecond )
82+ switch {
83+ case tt .publishError != nil :
84+ mocks .PubSub .EXPECT ().Publish (gomock .Any (), "order-logs" , gomock .Any ()).Return (tt .publishError )
85+ case ! tt .expectError :
86+ mocks .PubSub .EXPECT ().Publish (gomock .Any (), "order-logs" , gomock .Any ()).Return (nil )
87+ }
8388
84- testCases := []struct {
85- desc string
86- path string
87- body []byte
88- expectedStatusCode int
89- expectedError error
90- }{
91- {
92- desc : "valid order" ,
93- path : "/publish-order" ,
94- body : []byte (`{"data":{"orderId":"123","status":"pending"}}` ),
95- expectedStatusCode : http .StatusInternalServerError ,
96- },
97- {
98- desc : "valid product" ,
99- path : "/publish-product" ,
100- body : []byte (`{"data":{"productId":"123","price":"599"}}` ),
101- expectedStatusCode : http .StatusInternalServerError ,
102- },
89+ testHandler (t , tt .name , order , mockContainer , tt .body , tt .expectError , tt .expectedResult )
90+ })
10391 }
92+ }
10493
105- c := http.Client {}
94+ func TestProductFunction (t * testing.T ) {
95+ ctrl := gomock .NewController (t )
96+ defer ctrl .Finish ()
10697
107- for i , tc := range testCases {
108- req , _ := http .NewRequest (http .MethodPost , host + tc .path , bytes .NewBuffer (tc .body ))
109- req .Header .Set ("content-type" , "application/json" )
110- resp , err := c .Do (req )
98+ tests := []struct {
99+ name string
100+ body string
101+ expectError bool
102+ publishError error
103+ expectedResult interface {}
104+ }{
105+ {"valid product" , `{"productId":"123","price":"599"}` , false , nil , "Published" },
106+ {"invalid JSON" , `{"productId":,"price":"599"}` , true , nil , nil },
107+ {"publish error" , `{"productId":"123","price":"599"}` , true , fmt .Errorf ("publish failed" ), nil },
108+ }
111109
112- assert .Equal (t , tc .expectedStatusCode , resp .StatusCode , "TEST[%d], Failed.\n %s" , i , tc .desc )
113- require .NoError (t , err , "TEST[%d], Failed.\n %s" , i , tc .desc )
110+ for _ , tt := range tests {
111+ t .Run (tt .name , func (t * testing.T ) {
112+ mockContainer , mocks := container .NewMockContainer (t )
114113
115- defer resp .Body .Close ()
114+ switch {
115+ case tt .publishError != nil :
116+ mocks .PubSub .EXPECT ().Publish (gomock .Any (), "products" , gomock .Any ()).Return (tt .publishError )
117+ case ! tt .expectError :
118+ mocks .PubSub .EXPECT ().Publish (gomock .Any (), "products" , gomock .Any ()).Return (nil )
119+ }
120+
121+ testHandler (t , tt .name , product , mockContainer , tt .body , tt .expectError , tt .expectedResult )
122+ })
116123 }
117124}
125+
126+ func testHandler (t * testing.T , name string , handler func (* gofr.Context ) (interface {}, error ),
127+ container * container.Container , body string , expectError bool , expectedResult interface {}) {
128+
129+ t .Run (name , func (t * testing.T ) {
130+ ctx := & gofr.Context {
131+ Context : context .Background (),
132+ Request : & testRequest {Request : httptest .NewRequest (http .MethodPost , "/" , bytes .NewReader ([]byte (body ))), body : body },
133+ Container : container ,
134+ ContextLogger : * logging .NewContextLogger (context .Background (), container .Logger ),
135+ }
136+
137+ result , err := handler (ctx )
138+
139+ assert .Equal (t , expectError , err != nil , "error presence mismatch" )
140+ assert .Equal (t , expectedResult , result , "result mismatch" )
141+ })
142+ }
143+
144+ type testRequest struct {
145+ * http.Request
146+ body string
147+ }
148+
149+ func (r * testRequest ) Bind (v interface {}) error {
150+ return json .Unmarshal ([]byte (r .body ), v )
151+ }
152+
153+ func (r * testRequest ) Param (key string ) string { return r .URL .Query ().Get (key ) }
154+ func (r * testRequest ) PathParam (key string ) string { return "" }
155+ func (r * testRequest ) HostName () string { return r .Host }
156+ func (r * testRequest ) Params (key string ) []string { return r .URL .Query ()[key ] }
0 commit comments