Skip to content

Commit 3cd41d0

Browse files
authored
Merge pull request #2403 from gofr-dev/fix/publisher_test
2 parents 512e8b5 + 3f35821 commit 3cd41d0

File tree

3 files changed

+241
-130
lines changed

3 files changed

+241
-130
lines changed

examples/using-publisher/main_test.go

Lines changed: 104 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,35 @@ package main
22

33
import (
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

1724
func 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] }

examples/using-subscriber/main.go

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -10,41 +10,45 @@ func main() {
1010

1111
app.Migrate(migrations.All())
1212

13-
app.Subscribe("products", func(c *gofr.Context) error {
14-
var productInfo struct {
15-
ProductId string `json:"productId"`
16-
Price string `json:"price"`
17-
}
13+
app.Subscribe("products", productHandler)
1814

19-
err := c.Bind(&productInfo)
20-
if err != nil {
21-
c.Logger.Error(err)
15+
app.Subscribe("order-logs", orderHandler)
2216

23-
return nil
24-
}
17+
app.Run()
18+
}
19+
20+
func productHandler(c *gofr.Context) error {
21+
var productInfo struct {
22+
ProductId string `json:"productId"`
23+
Price string `json:"price"`
24+
}
2525

26-
c.Logger.Info("Received product", productInfo)
26+
err := c.Bind(&productInfo)
27+
if err != nil {
28+
c.Logger.Error(err)
2729

2830
return nil
29-
})
31+
}
3032

31-
app.Subscribe("order-logs", func(c *gofr.Context) error {
32-
var orderStatus struct {
33-
OrderId string `json:"orderId"`
34-
Status string `json:"status"`
35-
}
33+
c.Logger.Info("Received product", productInfo)
3634

37-
err := c.Bind(&orderStatus)
38-
if err != nil {
39-
c.Logger.Error(err)
35+
return nil
36+
}
4037

41-
return nil
42-
}
38+
func orderHandler(c *gofr.Context) error {
39+
var orderStatus struct {
40+
OrderId string `json:"orderId"`
41+
Status string `json:"status"`
42+
}
4343

44-
c.Logger.Info("Received order", orderStatus)
44+
err := c.Bind(&orderStatus)
45+
if err != nil {
46+
c.Logger.Error(err)
4547

4648
return nil
47-
})
49+
}
4850

49-
app.Run()
51+
c.Logger.Info("Received order", orderStatus)
52+
53+
return nil
5054
}

0 commit comments

Comments
 (0)