Here is my go project code structure with implementation:
--- Folder structure ---
gitlab.com/myproject/
modules/
itemcategory/
- itemcategorymanager.go
- itemcategorymanager_test.go
dataacess/
model/
- itemcategorymodel.go
--- itemcategorymanager.go ---
package itemcategory
type ItemCategoryDM interface{
AddToDB(...) error
WithTransaction(toExecute func(dm *model.ItemCategoryModel) error) error
}
type ItemCategoryManager struct {
itemCategoryDM ItemCategoryDM
}
func (m ItemCategoryManager) AddItemCategoryToDB(...) {
if err := m.itemCategoryDM.WithTransaction(
func(dm *model.ItemCategoryModel) error {
...
dm.AddToDB(...)
m.DoOtherStuff(...)
...
}
); err != nil {...}
}
func (m ItemCategoryManager) DoOtherStuff(...) error {...}
--- itemcategorymodel.go ---
package model
type ItemCategoryModel struct {
orm ThirdPartyORM
}
func NewItemCategoryModel(orm ThridPartyORM) *ItemCategoryModel {
return &ItemCategoryModel{orm: orm}
}
func (m ItemCategoryModel) AddToDB(...) error {...}
func (m ItemCategoryModel) WithTransaction(toExecute func(dm *ItemCategoryModel) error) error {
return m.orm.WithTransactionDB(func(txn ThirdPartyORM) error {
return toExecute(NewItemCategoryModel(txn))
})
}
The problem that I have is that, how can I gomock test this method itemcategory.AddItemCategoryToDB
when I am importing (dm *model.ItemCategoryModel)
?
Here is what I have tried, but how to mock myModel.AddToDB(...)
?
myModel := &model.ItemCategoryModel{}
itemCategoryDM := NewMockItemCategoryDM(mockController)
itemCategoryDM.
EXPECT().
WithTransaction(gomock.Any(), gomock.Any()).
Do(func(toExecute func(dm *model.ItemCategoryModel) error) {
err := toExecute(myModel)
assert.NoError(t, err)
}).
Return(nil).
Times(1)
itemCategoryDM.EXPECT().DoOtherStuff(...).Return(nil).Times(1)
Note that you cannot mock package model under itemcategorymodel.go
because there is no interface defined.
If your answer is to change (dm *model.ItemCategoryModel)
to (dm *ItemCategoryDM)
, it cannot work because the package model inside itemcategorymodel.go
, it will need to import the business layer itemcategorymanager.go
, ItemCategoryDM
interface, which causes cyclic dependencies (cause package itemcategory is currently calling/importing package model somewhere else in the code).
If your answer is to move interface to other packages, it will not be ideal/consistent since in the current project structure, every interface is belong in the package that uses values of the interface type (https://github.com/golang/go/wiki/CodeReviewComments#interfaces).
Any suggestions?