Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Calling sql.db's Ping functiion returns error #83

Closed
laynax opened this issue May 31, 2017 · 7 comments
Closed

Calling sql.db's Ping functiion returns error #83

laynax opened this issue May 31, 2017 · 7 comments
Labels
unrelated Topics unrelated to the project (i.e. Go usage or other libraries)

Comments

@laynax
Copy link

laynax commented May 31, 2017

No description provided.

@l3pp4rd
Copy link
Member

l3pp4rd commented May 31, 2017

it cannot return an error.
can you provide your test case implementation or minimal test in order to reproduce it? Currently Ping is not mockable, but it does not return error, regarding older go versions prior 1.8. it should also simply open a connection when a ping is called without any error.

@l3pp4rd l3pp4rd added the unrelated Topics unrelated to the project (i.e. Go usage or other libraries) label Jun 2, 2017
@mhemmings
Copy link

I have found it to return an error on Ping() too, but this only happens when SetMaxIdleConns(0) (which is perfectly valid way to remove pooling).

The error goes away when max idle connections is >0

@l3pp4rd
Copy link
Member

l3pp4rd commented Jun 15, 2017

yes that makes sense @mhemmings thanks for pointing it

@Radranic
Copy link

Radranic commented Feb 6, 2020

I've found another case where calling Ping causes errors.

I used go-sqlmock by switching out the driver name in the sql.Open call. This results in getting the error "expected a connection to be available, but it is not" as the mock open call only returns connections that were created with New.

Given that Open in most real drivers returns a new connection based off the currently provided connection string would it not make sense to also emulate this behavior?

@BonnieMilian
Copy link

BonnieMilian commented Mar 12, 2020

Reproducible code:

Function to be tested:

type responseHealth struct {
	Healthy bool `json:"healthy"`
	SQL     bool `json:"sqlDB"`
}

func (s *Server) handleHealth() http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		log.Info("handle health")

		dbHealthy := true

		db, errConnection := sql.Open("mysql", mysqlConnection)
		if errConnection != nil {
			dbHealthy = false
		}
		defer db.Close()

		errPing := db.Ping()
		if errPing != nil {
			dbHealthy = false
		}

		log.Info("Health Checked")
		res := responseHealth{
			Healthy: dbHealthy,
			SQL:     dbHealthy,
		}
		
                w.Header().Set("Content-Type", "application/json")
                response, errorToJSON := json.Marshal(res)
                if errorToJSON != nil {
                	w.WriteHeader(http.StatusInternalServerError)
                	io.WriteString(w, `{"success": false, error: "internal error"}`)
			return
		}

		w.WriteHeader(http.StatusOK)
		w.Write(response)
	}
}

Test:

func TestHandleHealth(t *testing.T) {
	db, mock, errOpenDBTests := sqlmock.New()
	if errOpenDBTests != nil {
		t.Fatalf("An error '%s' was not expected when opening a stub database connection for tests", errOpenDBTests)
	}
	defer db.Close()

	mock.ExpectPing()

	api := &server.Server{}
	api.InitializeServer()

	request, err := http.NewRequest("GET", "/v2/health", nil)
	if err != nil {
		t.Fatalf("error request %v", err)
	}

	w := httptest.NewRecorder()
	api.Router.ServeHTTP(w, request)

	if status := w.Code; status != http.StatusOK {
		t.Errorf(fmt.Sprintf("Health wrong Status: expected '%v' received '%v'", http.StatusOK, status))
	}

	expected := `{"healthy":true,"sqlDB":true}`
	if body := w.Body.String(); body != expected {
		t.Errorf("Health wrong Body: expected '%v' received '%v'", expected, body)
	}
}

But when the Ping is made the error is "connection refused"

@l3pp4rd
Copy link
Member

l3pp4rd commented Mar 13, 2020

Your code does not use an sqlmock db in your http server function, instead it opens mysql. If you would not just defer close sqlmock db, but instead check if all expectations were met like all examples in API docs show. It would give you an error that ping was never called

learn the library first, start from reading api docs and examples.

@rmulley
Copy link
Collaborator

rmulley commented Sep 15, 2020

@l3pp4rd Do we feel comfortable closing this issue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
unrelated Topics unrelated to the project (i.e. Go usage or other libraries)
Projects
None yet
Development

No branches or pull requests

7 participants