I am setting up a rest service in go using MongoDB and mux routers. I am running into issues on how to best set this up to allow for unit/integration testing in a separate database.
I have tried setting up the database in the Init() function but this is giving me issues when trying to set up unit tests using a test DB.
Here are some examples of where I am at right now. I am trying to use a method to connect to the database before posting so in my test I can connect to a different testing database.
type user struct {
name string `json:"name"`
age int `json:"age"`
}
type database struct {
db *mongo.Database
}
func ConnectToDB() (*database, error) {
client, err := mongo.NewClient(options.Client().ApplyURI("mongodb://localhost:27017"))
if err != nil {
return nil, err
}
if err := client.Connect(context.Background()); err != nil {
return nil, err
}
database := &database{
db: client.Database("PMBaseGo"),
}
return database, nil
}
func PostUser(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
//Retrieving request body
var user user
_ = json.NewDecoder(r.Body).Decode(&user)
//Posting Company.
err := PostUserToDB(user)
//Error Handling
if err != nil {
fmt.Println(err)
w.WriteHeader(500)
}
}
func (d *database) connPostUserToDB(user user) error {
_, err := d.db.Collection("companies").InsertOne(context.Background(), user)
if err != nil {
return err
}
return nil
}
func main() {
_, _ = ConnectToDB()
r := mux.NewRouter()
r.HandleFunc("/user", PostUser).Methods("POST")
fmt.Println("Application Running...")
log.Fatal(http.ListenAndServe("localhost:8081", r))
}
The issue I am at right now is trying to call the PostUserToDB
method in the PostUser
function.
I'm starting to think the issue lies prior to this in how I am going about connecting to the DB.
Make your handler a method on a struct that holds the handler's dependencies:
type server struct {
srv *service
}
type service struct {
db *mongo.Database
}
func (s *server) PostUser(w http.ResponseWriter, r *http.Request) {
// Create user struct from request data...
if err := s.srv.CreateUser(u); err != nil {
// Error response.
}
// Success response.
}
func (s *service) CreateUser(u *user) error {
// ...
_, err := d.db.Collection("foo").InsertOne(r.Context(), user)
return err
}
func main() {
s := &server{
srv: &service{
db: getMongoDatabase(),
},
}
r := mux.NewRouter()
r.HandleFunc("/user", s.PostUser).Methods("POST")
log.Fatal(http.ListenAndServe("localhost:8081", r))
}
In your test code, you can simply inject a different database to have your tests operate on that database.