When one main method handles an entire translation request, testing becomes difficult. A system under test (SUT) gives each test a clear boundary: treat the unit as a black box, provide inputs, and assert that its outputs are correct. section 3.1
A translation service can be divided into three testable SUTs:
- Service: applies the business logic, such as translating a word for a language. section 3.1
- Handler: converts requests into service inputs and returns the results. section 3.1
- Server: runs the handler and connects the whole flow. section 3.1
A focused translation test
Given a word, when it is translated into English, then the test should return the expected word. This given-when-then structure turns a business behavior into a concrete test expectation. section 3.1
Listing 3.1 Main.go
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
)
func main() {
addr := ":8080"
mux := http.NewServeMux()
mux.HandleFunc("/hello",
func(w http.ResponseWriter, r *http.Request) {
enc := json.NewEncoder(w)
w.Header().
Set("Content-Type",
"application/json; charset=utf-8")
resp := Resp{
Language: "English",
Translation: "Hello",
}
if err := enc.Encode(resp); err != nil {
panic("unable to encode response")
}
})
log.Printf("listening on %s\n", addr)
log.Fatal(http.ListenAndServe(addr, mux))
}
type Resp struct {
Language string `json:"language"`
Translation string `json:"translation"`
}
The initial Go server keeps the response and HTTP handling together, illustrating why separating service, handler, and server boundaries improves testability. section 3.1



