다음과 같이 쓸 수 있을 것이다.
package mqevent
import amqp "github.com/rabbitmq/amqp091-go"
type MQ interface {
MqChannel() (*amqp.Channel, error)
PublishToExchange(orgid, userid, messageType, message string, ch *amqp.Channel) error
DeleteQueue(orgid, userid, queueNumber string, ch *amqp.Channel) error
DeclareExchange(orgid string, ch *amqp.Channel) error
DeclareQueue(orgid, userid, queueNumber string, ch *amqp.Channel) (amqp.Queue, error)
BindQueue(orgid, userid string, que amqp.Queue, ch *amqp.Channel) error
PublishToPublic(orgid, userid string, ch *amqp.Channel) error
CountQueueBoundedToExchange(orgId string) (int, error)
DeclareDeadQue(ch *amqp.Channel) (amqp.Queue, error)
BindDeadQue(que amqp.Queue, ch *amqp.Channel) error
}
var Mqutil MQ
배포 환경에서 사용되는 실제 함수들은 테스팅이 쉽도록 따로 모음집으로 구현한다.
이때 테스팅을 용이하게 하기위해 진짜로 테스트하고 싶은 기능만 포함되도록 함수를 구현해야하는것이 중요하다
package mqConnection
...
type MQ struct {
}
func (q *MQ) MqChannel() (*amqp.Channel, error) {
ch, err := connection.RabbitConn.Channel()
if err != nil {
return nil, err
}
return ch, nil
}
func (q *MQ) PublishToExchange(orgid, userid, message, messageType string, ch *amqp.Channel) error {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
err := ch.PublishWithContext(ctx,
orgid, // exchange
orgid+"."+userid+"."+messageType, // routing key
false, // mandatory
false, // immediate
amqp.Publishing{
ContentType: "text/plain",
Body: []byte(message),
})
if err != nil {
return err
}
return nil
}
....
package mqConnection
import (
amqp "github.com/rabbitmq/amqp091-go"
)
type MockMQ struct {
}
func (q *MockMQ) MqChannel() (*amqp.Channel, error) {
return nil, nil
}
func (q *MockMQ) PublishToExchange(orgid, userid, message, messageType string, ch *amqp.Channel) error {
return nil
}
...
package application
import (
"bytes"
"fmt"
"mqlistener/pkg/mqevent"
"mqlistener/pkg/mqevent/mqConnection"
"net/http"
"net/http/httptest"
"testing"
)
func TestPublishQue(t *testing.T) {
**mqevent.Mqutil = &mqConnection.MockMQ{} //모든 메서드를 다 mock했음:) 이게다임**
//나머지는 table driven test 방식대로 하면됨.
tests := []struct {
name string
orgId string
userId string
queueNumber string
message string
messageType string
resign bool
expectedStatusCode int
}{
{"PublishSuccess", "h00002", "hiosi", "1", "disconnect", "disconnect", true, http.StatusCreated},
}
for _, e := range tests {
w := httpPublishReq(e.orgId, e.userId, e.queueNumber, e.message, e.messageType, e.resign)
if e.expectedStatusCode != w.Result().StatusCode {
t.Errorf("for %s: expected status %v, but got %v", e.name, e.expectedStatusCode, w.Result().StatusCode)
}
}
}
func httpPublishReq(orgid, userid, queueNumber, message, messageType string, resign bool) *httptest.ResponseRecorder {
r := SetUpRouter()
r.POST("/publishQue", PublishQueInfo)
jsonBody := []byte(fmt.Sprintf(`{"orgId": "%v", "userId":"%v", "queueNumber": "%v","message": "%v", "messageType": "%v", "resign": %v}`, orgid, userid, queueNumber, message, messageType, resign))
bodyReader := bytes.NewReader(jsonBody)
req, _ := http.NewRequest("POST", "/publishQue", bodyReader)
w := httptest.NewRecorder()
r.ServeHTTP(w, req)
return w
}
배포 환경에서 쓰는 코드
package application
import (
"encoding/json"
"errors"
"mqlistener/pkg/mqevent"
"mqlistener/pkg/request"
"net/http"
"github.com/gin-gonic/gin"
)
func PublishQueInfo(c *gin.Context) {
var req *http.Request = c.Request
auth := new(AuthPayload)
err := json.NewDecoder(req.Body).Decode(auth)
if err != nil {
request.BadRequest("사용자 정보를 바르게 입력하세요", c)
return
}
//MessageType: public private
//Message: disconnect, other messages....
queueName, err := PublishQue(auth.OrgId, auth.UserId, auth.QueueNumber, auth.Message, auth.MessageType, auth.Resign)
if err != nil {
request.BadRequest("존재하지 않는 큐 입니다.", c)
return
}
request.CreatedQue("큐에 메세지를 전달하였습니다", queueName, c)
}
func PublishQue(orgid, userid, queueNumber, message, messageType string, resign bool) (string, error) {
err := checkMessageType(messageType)
if err != nil {
return "", err
}
ch, err := mqevent.Mqutil.MqChannel()
if err != nil {
return "", err
}
err = mqevent.Mqutil.PublishToExchange(orgid, userid, message, messageType, ch)
if err != nil {
return "", err
}
queueName := orgid + "." + userid + "." + queueNumber
return queueName, nil
}
func checkMessageType(messageType string) error {
if messageType != "disconnect" && messageType != "public" && messageType != "private" {
return errors.New("messageType이 틀렸습니다")
}
return nil
}