Tests Everywhere - Go
Tags: test, go, tutorial
Published: 2023-11-22 23:56:58

{% github rogervinas/tests-everywhere no-readme %}

[Go](https://go.dev/) testing [this simple Hello World](https://dev.to/rogervinas/tests-tests-everywhere-1b6h) with [Standard library](https://pkg.go.dev/testing)

- [Show me the code](#show-me-the-code)
  - [Implementation](#implementation)
  - [Test](#test)
- [Run this project using 🐳 docker](https://github.com/rogervinas/tests-everywhere/tree/main/go#run-this-project-using--docker)
- [Run this project locally](https://github.com/rogervinas/tests-everywhere/tree/main/go#run-this-project-locally)

## Show me the code

### Implementation

1. Create `HelloMessage` interface and `HelloWorldMessage` implementation in [HelloMessage.go](https://github.com/rogervinas/tests-everywhere/blob/main/go/HelloMessage.go):

```go
type HelloMessage interface {
  Text() string
}

type HelloWorldMessage struct{}

func (message *HelloWorldMessage) Text() string {
  return "Hello World!"
}
```

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

2. Same way create `HelloConsole` interface and `HelloSystemConsole` implementation in [HelloConsole.go](https://github.com/rogervinas/tests-everywhere/blob/main/go/HelloConsole.go):

```go
type HelloConsole interface {
  Print(text string)
}

type HelloSystemConsole struct{}

func (console *HelloSystemConsole) Print(text string) {
  fmt.Println(text)
}
```

3. Create `HelloApp` class in [HelloApp.go](https://github.com/rogervinas/tests-everywhere/blob/main/go/HelloApp.go):

```go
type HelloApp struct {
  message HelloMessage
  console HelloConsole
}

func (app *HelloApp) PrintHello() {
  app.console.Print(app.message.Text())
}
```

4. Create main function in [Main.go](https://github.com/rogervinas/tests-everywhere/blob/main/go/Main.go) that wraps it all together:

```go
func main() {
  message := HelloWorldMessage{}
  console := HelloSystemConsole{}
  app := HelloApp{&message, &console}
  app.PrintHello()
}
```

### Test

Following [Standard library > testing](https://pkg.go.dev/testing) guide ...

1. Test `HelloMessage` in [HelloMessage_test.go](https://github.com/rogervinas/tests-everywhere/blob/main/go/HelloMessage_test.go):

```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())
  }
}
```

2. Test `HelloApp` in [HelloApp_test.go](https://github.com/rogervinas/tests-everywhere/blob/main/go/HelloApp_test.go):

```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)
  }
}
```

3. Test output should look like:

```
=== RUN   TestShouldReturnPrintHelloMessage
--- PASS: TestShouldReturnPrintHelloMessage (0.00s)
=== RUN   TestShouldReturnHelloWorld
--- PASS: TestShouldReturnHelloWorld (0.00s)
PASS
ok      org.hello/main  0.412s
```

Happy Testing! 💙