Implements /transactions PUT method
Adds PUT method to OpenAPI spec. Given that the transaction IDs are generated on server-side, for the PUT method to remain idempotent, it can only update existing transactions. It also adds a TransactionExists method on the DAL. Issue: #20
This commit is contained in:
parent
4c82ca0e2b
commit
55bd87c864
@ -73,6 +73,21 @@ paths:
|
|||||||
$ref: "#/components/schemas/Transaction"
|
$ref: "#/components/schemas/Transaction"
|
||||||
"400":
|
"400":
|
||||||
description: Transaction not created
|
description: Transaction not created
|
||||||
|
put:
|
||||||
|
summary: Update an existing transaction
|
||||||
|
operationId: updateTransaction
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
allOf:
|
||||||
|
- $ref: "#/components/schemas/Transaction"
|
||||||
|
- required:
|
||||||
|
- id
|
||||||
|
|
||||||
|
responses:
|
||||||
|
"204":
|
||||||
|
description: Transaction updated successfully
|
||||||
|
|
||||||
/transaction/{transactionId}:
|
/transaction/{transactionId}:
|
||||||
get:
|
get:
|
||||||
|
|||||||
@ -83,11 +83,39 @@ func (server *ServerImpl) CreateTransaction(ctx echo.Context) error {
|
|||||||
return ctx.NoContent(http.StatusBadRequest)
|
return ctx.NoContent(http.StatusBadRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
ans, err := server.Dal.InsertTransaction(transaction2entity(*t))
|
transaction, err := server.Dal.InsertTransaction(transaction2entity(*t))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("%v", err)
|
log.Printf("%v", err)
|
||||||
return ctx.NoContent(http.StatusInternalServerError)
|
return ctx.NoContent(http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ctx.JSON(http.StatusCreated, entity2transaction(ans))
|
return ctx.JSON(http.StatusCreated, entity2transaction(transaction))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (server *ServerImpl) UpdateTransaction(ctx echo.Context) error {
|
||||||
|
t := new(Transaction)
|
||||||
|
if err := ctx.Bind(t); err != nil {
|
||||||
|
log.Printf("%v", err)
|
||||||
|
return ctx.NoContent(http.StatusBadRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
transaction := transaction2entity(*t)
|
||||||
|
|
||||||
|
exists, err := server.Dal.TransactionExists(transaction.Id)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("%v", err)
|
||||||
|
return ctx.NoContent(http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
|
||||||
|
if exists {
|
||||||
|
transaction, err := server.Dal.UpdateTransaction(transaction)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("%v", err)
|
||||||
|
return ctx.NoContent(http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx.JSON(http.StatusOK, entity2transaction(transaction))
|
||||||
|
} else {
|
||||||
|
return ctx.NoContent(http.StatusNotFound)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -286,3 +286,80 @@ func TestServerImpl_CreateTransaction(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestServerImpl_UpdateTransaction(t *testing.T) {
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
|
||||||
|
date, _ := time.Parse(time.DateOnly, "1974-04-25")
|
||||||
|
|
||||||
|
m := mock.NewMockDAL(ctrl)
|
||||||
|
e := m.EXPECT()
|
||||||
|
|
||||||
|
type fields struct {
|
||||||
|
// Dal dal.DAL
|
||||||
|
fn func(any) *gomock.Call
|
||||||
|
args any
|
||||||
|
returns any
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
type args struct {
|
||||||
|
request string
|
||||||
|
}
|
||||||
|
type want struct {
|
||||||
|
status int
|
||||||
|
body string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields []fields
|
||||||
|
args args
|
||||||
|
want want
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"UpdateExisting",
|
||||||
|
[]fields{
|
||||||
|
{e.TransactionExists, gomock.Any(), true, nil},
|
||||||
|
{e.UpdateTransaction, gomock.Any(), entity.Transaction{Id: 1, Date: date, Description: "freedom", Value: decimal.New(9000, 0)}, nil},
|
||||||
|
},
|
||||||
|
args{`{"date":"1974-04-25","description":"freedom","id":1,"value":9000}`},
|
||||||
|
want{200, `{"date":"1974-04-25","description":"freedom","id":1,"value":9000}`},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"NotExisting",
|
||||||
|
[]fields{
|
||||||
|
{e.TransactionExists, gomock.Any(), false, nil},
|
||||||
|
},
|
||||||
|
args{`{"date":"1974-04-25","description":"freedom","id":1,"value":9000}`},
|
||||||
|
want{404, ""},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
server := &ServerImpl{
|
||||||
|
Dal: m,
|
||||||
|
}
|
||||||
|
for _, expect := range tt.fields {
|
||||||
|
expect.fn(expect.args).Return(expect.returns, expect.err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rec := httptest.NewRecorder()
|
||||||
|
req := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(tt.args.request))
|
||||||
|
req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON)
|
||||||
|
ctx := echo.New().NewContext(req, rec)
|
||||||
|
|
||||||
|
if err := server.UpdateTransaction(ctx); (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("ServerImpl.UpdateTransaction() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
}
|
||||||
|
if got := rec.Code; !reflect.DeepEqual(got, tt.want.status) {
|
||||||
|
t.Errorf("ServerImpl.UpdateTransaction() = %v, want %v", got, tt.name)
|
||||||
|
}
|
||||||
|
if got := strings.TrimSpace(rec.Body.String()); !reflect.DeepEqual(got, tt.want.body) {
|
||||||
|
t.Errorf("ServerImpl.UpdateTransaction() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -59,9 +59,21 @@ type GetTransactionsParams struct {
|
|||||||
Sort *string `form:"sort,omitempty" json:"sort,omitempty"`
|
Sort *string `form:"sort,omitempty" json:"sort,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateTransactionJSONBody defines parameters for UpdateTransaction.
|
||||||
|
type UpdateTransactionJSONBody struct {
|
||||||
|
Category *string `json:"category,omitempty"`
|
||||||
|
Date openapi_types.Date `json:"date"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Id int64 `json:"id"`
|
||||||
|
Value float32 `json:"value"`
|
||||||
|
}
|
||||||
|
|
||||||
// CreateTransactionJSONRequestBody defines body for CreateTransaction for application/json ContentType.
|
// CreateTransactionJSONRequestBody defines body for CreateTransaction for application/json ContentType.
|
||||||
type CreateTransactionJSONRequestBody = Transaction
|
type CreateTransactionJSONRequestBody = Transaction
|
||||||
|
|
||||||
|
// UpdateTransactionJSONRequestBody defines body for UpdateTransaction for application/json ContentType.
|
||||||
|
type UpdateTransactionJSONRequestBody UpdateTransactionJSONBody
|
||||||
|
|
||||||
// ServerInterface represents all server handlers.
|
// ServerInterface represents all server handlers.
|
||||||
type ServerInterface interface {
|
type ServerInterface interface {
|
||||||
// Find bank by ID
|
// Find bank by ID
|
||||||
@ -79,6 +91,9 @@ type ServerInterface interface {
|
|||||||
// Create a new transaction
|
// Create a new transaction
|
||||||
// (POST /transactions)
|
// (POST /transactions)
|
||||||
CreateTransaction(ctx echo.Context) error
|
CreateTransaction(ctx echo.Context) error
|
||||||
|
// Update an existing transaction
|
||||||
|
// (PUT /transactions)
|
||||||
|
UpdateTransaction(ctx echo.Context) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServerInterfaceWrapper converts echo contexts to parameters.
|
// ServerInterfaceWrapper converts echo contexts to parameters.
|
||||||
@ -182,6 +197,15 @@ func (w *ServerInterfaceWrapper) CreateTransaction(ctx echo.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateTransaction converts echo context to params.
|
||||||
|
func (w *ServerInterfaceWrapper) UpdateTransaction(ctx echo.Context) error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
// Invoke the callback with all the unmarshaled arguments
|
||||||
|
err = w.Handler.UpdateTransaction(ctx)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// This is a simple interface which specifies echo.Route addition functions which
|
// This is a simple interface which specifies echo.Route addition functions which
|
||||||
// are present on both echo.Echo and echo.Group, since we want to allow using
|
// are present on both echo.Echo and echo.Group, since we want to allow using
|
||||||
// either of them for path registration
|
// either of them for path registration
|
||||||
@ -215,28 +239,30 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL
|
|||||||
router.GET(baseURL+"/transaction/:transactionId", wrapper.GetTransactionById)
|
router.GET(baseURL+"/transaction/:transactionId", wrapper.GetTransactionById)
|
||||||
router.GET(baseURL+"/transactions", wrapper.GetTransactions)
|
router.GET(baseURL+"/transactions", wrapper.GetTransactions)
|
||||||
router.POST(baseURL+"/transactions", wrapper.CreateTransaction)
|
router.POST(baseURL+"/transactions", wrapper.CreateTransaction)
|
||||||
|
router.PUT(baseURL+"/transactions", wrapper.UpdateTransaction)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Base64 encoded, gzipped, json marshaled Swagger object
|
// Base64 encoded, gzipped, json marshaled Swagger object
|
||||||
var swaggerSpec = []string{
|
var swaggerSpec = []string{
|
||||||
|
|
||||||
"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",
|
||||||
"jkMmmIZdTHto9N8AAAD//+YRCdlGDQAA",
|
"FkMmmIFdH/aIepgB/VMjvxvoQusPVZTJ1392H8Z/pR6OD7NNOXMkhFiHZP7EY70fYdOWyoSZJWakwr8B",
|
||||||
|
"AAD//5ap8eBoDgAA",
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSwagger returns the content of the embedded swagger specification file
|
// GetSwagger returns the content of the embedded swagger specification file
|
||||||
|
|||||||
@ -6,6 +6,8 @@ type DAL interface {
|
|||||||
Transaction(transactionId int64) (*entity.Transaction, error)
|
Transaction(transactionId int64) (*entity.Transaction, error)
|
||||||
Transactions() (entity.Transactions, error)
|
Transactions() (entity.Transactions, error)
|
||||||
InsertTransaction(entity.Transaction) (entity.Transaction, error)
|
InsertTransaction(entity.Transaction) (entity.Transaction, error)
|
||||||
|
UpdateTransaction(entity.Transaction) (entity.Transaction, error)
|
||||||
|
TransactionExists(uint64) (bool, error)
|
||||||
Bank(bankId string) (*entity.Bank, error)
|
Bank(bankId string) (*entity.Bank, error)
|
||||||
Banks() (entity.Banks, error)
|
Banks() (entity.Banks, error)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package dal
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"errors"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"git.rosemyrtle.work/personal-finance/server/internal/entity"
|
"git.rosemyrtle.work/personal-finance/server/internal/entity"
|
||||||
@ -68,6 +69,60 @@ func (dal *DalImpl) InsertTransaction(t entity.Transaction) (entity.Transaction,
|
|||||||
return t, nil
|
return t, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (dal *DalImpl) UpdateTransaction(t entity.Transaction) (entity.Transaction, error) {
|
||||||
|
log.Print("DAL::UpdateTransaction")
|
||||||
|
|
||||||
|
if dal.Db == nil {
|
||||||
|
log.Panic("database not available")
|
||||||
|
}
|
||||||
|
|
||||||
|
stmt := `
|
||||||
|
UPDATE pfbudget.transactions
|
||||||
|
SET date = $2, description = $3, amount = $4
|
||||||
|
WHERE id = $1
|
||||||
|
`
|
||||||
|
|
||||||
|
result, err := dal.Db.Exec(stmt, t.Id, t.Date, t.Description, t.Value)
|
||||||
|
if err != nil {
|
||||||
|
return entity.Transaction{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
nAffected, err := result.RowsAffected()
|
||||||
|
if err != nil {
|
||||||
|
return entity.Transaction{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if nAffected != 1 {
|
||||||
|
return t, errors.New("more than 1 row affected")
|
||||||
|
}
|
||||||
|
|
||||||
|
return t, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dal *DalImpl) TransactionExists(id uint64) (bool, error) {
|
||||||
|
log.Print("DAL::TransactionExists")
|
||||||
|
|
||||||
|
if dal.Db == nil {
|
||||||
|
log.Panic("database not available")
|
||||||
|
}
|
||||||
|
|
||||||
|
stmt := `
|
||||||
|
SELECT EXISTS(
|
||||||
|
SELECT 1
|
||||||
|
FROM pfbudget.transactions
|
||||||
|
WHERE id = $1
|
||||||
|
)
|
||||||
|
`
|
||||||
|
|
||||||
|
exists := new(bool)
|
||||||
|
err := dal.Db.QueryRow(stmt, id).Scan(&exists)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return *exists, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (dal *DalImpl) Bank(bankId string) (*entity.Bank, error) {
|
func (dal *DalImpl) Bank(bankId string) (*entity.Bank, error) {
|
||||||
log.Printf("DAL::Bank(%v)", bankId)
|
log.Printf("DAL::Bank(%v)", bankId)
|
||||||
|
|
||||||
|
|||||||
@ -317,3 +317,110 @@ func TestDalImpl_InsertTransaction(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDalImpl_UpdateTransaction(t *testing.T) {
|
||||||
|
db, mock, err := sqlmock.New()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
date := time.Now()
|
||||||
|
|
||||||
|
type fields struct {
|
||||||
|
Db *sql.DB
|
||||||
|
}
|
||||||
|
type args struct {
|
||||||
|
t entity.Transaction
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
args args
|
||||||
|
want entity.Transaction
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"SuccessfulUpdate",
|
||||||
|
fields{db},
|
||||||
|
args{entity.Transaction{Id: entity.InvalidId, Date: date, Description: "freedom", Value: decimal.NewFromInt(9000)}},
|
||||||
|
entity.Transaction{Id: entity.InvalidId, Date: date, Description: "freedom", Value: decimal.NewFromInt(9000)},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
dal := &DalImpl{
|
||||||
|
Db: tt.fields.Db,
|
||||||
|
}
|
||||||
|
|
||||||
|
mock.
|
||||||
|
ExpectExec(`
|
||||||
|
UPDATE pfbudget.transactions
|
||||||
|
SET date = \$2, description = \$3, amount = \$4
|
||||||
|
WHERE id = \$1`).
|
||||||
|
WithArgs(tt.args.t.Id, tt.args.t.Date, tt.args.t.Description, tt.args.t.Value).
|
||||||
|
WillReturnResult(sqlmock.NewResult(0, 1))
|
||||||
|
|
||||||
|
got, err := dal.UpdateTransaction(tt.args.t)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("DalImpl.UpdateTransaction() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("DalImpl.UpdateTransaction() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDalImpl_TransactionExists(t *testing.T) {
|
||||||
|
db, mock, err := sqlmock.New()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
type fields struct {
|
||||||
|
Db *sql.DB
|
||||||
|
}
|
||||||
|
type args struct {
|
||||||
|
id uint64
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
args args
|
||||||
|
want bool
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{"TransactionExists", fields{db}, args{1}, true, false},
|
||||||
|
{"TransactionNotExists", fields{db}, args{1}, false, false},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
dal := &DalImpl{
|
||||||
|
Db: tt.fields.Db,
|
||||||
|
}
|
||||||
|
|
||||||
|
mock.
|
||||||
|
ExpectQuery(`
|
||||||
|
SELECT EXISTS\(
|
||||||
|
SELECT 1
|
||||||
|
FROM pfbudget.transactions
|
||||||
|
WHERE id = \$1
|
||||||
|
\)`).
|
||||||
|
WithArgs(tt.args.id).
|
||||||
|
WillReturnRows(
|
||||||
|
mock.NewRows([]string{"exists"}).
|
||||||
|
AddRows([]driver.Value{tt.want}),
|
||||||
|
)
|
||||||
|
|
||||||
|
got, err := dal.TransactionExists(tt.args.id)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("DalImpl.TransactionExists() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if got != tt.want {
|
||||||
|
t.Errorf("DalImpl.TransactionExists() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -99,6 +99,21 @@ func (mr *MockDALMockRecorder) Transaction(arg0 any) *gomock.Call {
|
|||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Transaction", reflect.TypeOf((*MockDAL)(nil).Transaction), arg0)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Transaction", reflect.TypeOf((*MockDAL)(nil).Transaction), arg0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TransactionExists mocks base method.
|
||||||
|
func (m *MockDAL) TransactionExists(arg0 uint64) (bool, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "TransactionExists", arg0)
|
||||||
|
ret0, _ := ret[0].(bool)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// TransactionExists indicates an expected call of TransactionExists.
|
||||||
|
func (mr *MockDALMockRecorder) TransactionExists(arg0 any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TransactionExists", reflect.TypeOf((*MockDAL)(nil).TransactionExists), arg0)
|
||||||
|
}
|
||||||
|
|
||||||
// Transactions mocks base method.
|
// Transactions mocks base method.
|
||||||
func (m *MockDAL) Transactions() ([]entity.Transaction, error) {
|
func (m *MockDAL) Transactions() ([]entity.Transaction, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
@ -113,3 +128,18 @@ func (mr *MockDALMockRecorder) Transactions() *gomock.Call {
|
|||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Transactions", reflect.TypeOf((*MockDAL)(nil).Transactions))
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Transactions", reflect.TypeOf((*MockDAL)(nil).Transactions))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateTransaction mocks base method.
|
||||||
|
func (m *MockDAL) UpdateTransaction(arg0 entity.Transaction) (entity.Transaction, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "UpdateTransaction", arg0)
|
||||||
|
ret0, _ := ret[0].(entity.Transaction)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateTransaction indicates an expected call of UpdateTransaction.
|
||||||
|
func (mr *MockDALMockRecorder) UpdateTransaction(arg0 any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateTransaction", reflect.TypeOf((*MockDAL)(nil).UpdateTransaction), arg0)
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user