DEV Community

Cover image for Tests Everywhere - Go
Roger Viñas Alcon
Roger Viñas Alcon

Posted on • Updated on

Tests Everywhere - Go

GitHub logo rogervinas / tests-everywhere

🤠 Tests, Tests Everywhere!

Go testing this simple Hello World with Standard library

Show me the code

Implementation

  1. Create HelloMessage interface and HelloWorldMessage implementation in HelloMessage.go:
type HelloMessage interface {
  Text() string
}

type HelloWorldMessage struct{}

func (message *HelloWorldMessage) Text() string {
  return "Hello World!"
}
Enter fullscreen mode Exit fullscreen mode

Creating it as an interface will allow us to mock it for testing.

  1. Same way create HelloConsole interface and HelloSystemConsole implementation in HelloConsole.go:
type HelloConsole interface {
  Print(text string)
}

type HelloSystemConsole struct{}

func (console *HelloSystemConsole) Print(text string) {
  fmt.Println(text)
}
Enter fullscreen mode Exit fullscreen mode
  1. Create HelloApp class in HelloApp.go:
type HelloApp struct {
  message HelloMessage
  console HelloConsole
}

func (app *HelloApp) PrintHello() {
  app.console.Print(app.message.Text())
}
Enter fullscreen mode Exit fullscreen mode
  1. Create main function in Main.go that wraps it all together:
func main() {
  message := HelloWorldMessage{}
  console := HelloSystemConsole{}
  app := HelloApp{&message, &console}
  app.PrintHello()
}
Enter fullscreen mode Exit fullscreen mode

Test

Following Standard library > testing guide ...

  1. Test HelloMessage in HelloMessage_test.go:
func TestShouldReturnHelloWorld(t *testing.T) {
  messageText := "Hello World!"
  message := HelloWorldMessage{}
  if message.Text() != messageText {
    t.Fatalf("Expected %s but got %s", messageText, message.Text())
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. Test HelloApp in HelloApp_test.go:
// 2.1 Define a HelloMessageMock struct that ...
type HelloMessageMock struct {
  text string
}

// ... fullfils HelloMessage interface
func (message *HelloMessageMock) Text() string {
  return message.text
}

// 2.2 Define a HelloConsoleMock that ...
type HelloConsoleMock struct {
  Calls int
  Text  string
}

// ... fullfills HelloConsole interface
func (console *HelloConsoleMock) Print(text string) {
  console.Calls++
  console.Text = text
}

func TestShouldReturnPrintHelloMessage(t *testing.T) {

  messageText := "Hello Test!"

  // 2.3 Create a HelloMessageMock
  // that will return "Hello Test!"
  message := HelloMessageMock{messageText}

  // 2.4 Create a HelloConsoleMock
  // that will capture its calls
  console := HelloConsoleMock{}

  // 2.5 Create a HelloApp, the one we want to test, passing the mocks
  app := HelloApp{&message, &console}
  // 2.6 Execute the method we want to test
  app.PrintHello()

  // 2.7 Assert HelloConsoleMock has been called once
  if console.Calls != 1 {
    t.Fatalf("HelloConsole expected calls 1 but got %d", console.Calls)
  }

  // 2.8 Assert HelloConsoleMock has been called with "Hello Test!"
  if console.Text != messageText {
    t.Fatalf("HelloConsole expected text %s but got %s", messageText, console.Text)
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. Test output should look like:
=== RUN   TestShouldReturnPrintHelloMessage
--- PASS: TestShouldReturnPrintHelloMessage (0.00s)
=== RUN   TestShouldReturnHelloWorld
--- PASS: TestShouldReturnHelloWorld (0.00s)
PASS
ok      org.hello/main  0.412s
Enter fullscreen mode Exit fullscreen mode

Happy Testing! 💙

Top comments (0)