Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redefine const in golang for test

I'm writing an http client for a service and for testing I want to use a net/http/httptest server instead of calling out to the remote API. I can easily do this if I make the baseUrl a global variable which gets set to the url of my test server. However, this makes the production code more fragile because baseUrl can also be changed during runtime. My preference would be to make baseUrl a const for production code but still be able to change.

package main
const baseUrl = "http://google.com"

// in main_test.go
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  ...
 }
const baseUrl = ts.URL
// above line throws const baseUrl already defined error
like image 894
Krut Avatar asked Nov 18 '15 07:11

Krut


People also ask

Should tests be in the same package Golang?

Writing tests in Go requires a test file link, and this test file must always end with _test.go . By convention, Go testing files are always located in the same folder, or package, where the code they are testing resides.

How do you define a const in Golang?

In Go, const is a keyword introducing a name for a scalar value such as 2 or 3.14159 or "scrumptious" . Such values, named or otherwise, are called constants in Go. Constants can also be created by expressions built from constants, such as 2+3 or 2+3i or math. Pi/2 or ("go"+"pher") .


1 Answers

If your code uses a const value, it is not testing-friendly (regarding testing with different values of that parameter).

You could approach your problem with a slight refactoring. Let's say you have a function that uses this const:

const baseUrl = "http://google.com"

func MyFunc() string {
    // use baseUrl
}

You could create another function that takes base URL as a parameter, and your original MyFunc() calls this:

const baseUrl_ = "http://google.com"

func MyFunc() string {
    // Call other function passing the const value
    return myFuncImpl(baseUrl_)
}

func myFuncImpl(baseUrl string) string {
    // use baseUrl
    // Same implementation that was in your original MyFunc() function
}

This way the API of your library doesn't change, but now you can test the functionality of your original MyFunc() by testing myFuncImpl(), and you can pass any value to test with.

Calling MyFunc() will remain safe as it always passes the const baseUrl_ to myFuncImpl() where the implementation now resides. It's your decision whether you make this new myFuncImpl() function exported or not; it may remain unexported as testing code may (should) be placed in the same package and can call it without problems.

like image 117
icza Avatar answered Sep 28 '22 03:09

icza