'How to test uber dig application Golang

I recently wanted to try out dependency injection in golang and I picked up Uber dig container everything working well but I am not sure how to test my code.

My dig container

func buildContainer() *dig.Container {
    container := dig.New()
    _ = container.Provide(config.GetInstance)
    _ = container.Provide(database.GetInstance)
    _ = container.Provide(evaluation.NewEvaluator)
    _ = container.Provide(repository.NewExperimentRepository)
    return container
}

My Dao

type ExperimentDao interface {

    // Create experiment
    Create(experiment *models.Experiment) error

    // Update experiment
    Update(experiment *models.Experiment) error

    // FindByID find experiment by id
    FindByID(id string) (*models.Experiment, error)

    //FindAll find all the questions
    FindAll(filter bson.M, page int, limit int) (*models.ExperimentPagination, error)
}

My Repository that implements the doa interface

type ExperimentRepository struct {
    DB *database.DB
}

// NewExperimentRepository returns new ExperimentDao
func NewExperimentRepository(db *database.DB) interfaces.ExperimentDao {
    return &ExperimentRepository{DB: db}
}

func (expRepo *ExperimentRepository) Create(experiment *models.Experiment) error {
    //repository code to insert in DB
}

// rest of the implemented func(s)

Here is my handler where I use the injected Repository to insert the data

func CreateExperiment(res http.ResponseWriter, req *http.Request) {

    experiment := models.Experiment{}

    err := json.NewDecoder(req.Body).Decode(&experiment)
    if err != nil {
        logrus.Error("Create Experiment Error parsing payload : ", err)
        utils.RespondError(res, err, 400)
        return
    }

    ValErr := ValidateExpt(experiment, "create")

    if ValErr != "" {
        logrus.Error("Create Experiment Error : ", ValErr)
        utils.Respond(res, ValErr, 400)
        return
    }

    di := container.GetInstance()
    err = di.Invoke(func(dao interfaces.ExperimentDao) {
        err := dao.Create(&experiment)
        if err != nil {
            utils.RespondError(res, err, http.StatusInternalServerError)
            return 
        }
        utils.Respond(res, "experiment created successfully", http.StatusOK)
    })

    if err != nil {
        logrus.Error("Insert Experiment Error : ", err)
        utils.RespondError(res, err, 400)
    }
}

// Di builder

func GetInstance() *dig.Container {
    once.Do(func() {
        container = buildContainer()
    })
    return container
}

Now as the code is working fine as expected so I hope the approach is correct as per my knowledge but now I am unable to figure out how to write the test to test this code I can write few validations for experiment model but not for repository, dao or the di container.

Can you guys help where should I look or what am I missing.

Thanks.



Solution 1:[1]

I would suggest you to write a function, that will receive all dependencies as parameters and will return the HTTP handler, like this:

func NewCreateExperimentHandler(c *dig.Container) http.HandlerFunc {
    return func (res http.ResponseWriter, req *http.Request) {
        // the current CreateExperiment() implementation 
    }
}

This will allow you to mock your container inside the tests.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Prisacari Dmitrii