1

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?

Victor Vic
  • 23
  • 3

0 Answers0