34

I'm struggling to do table driven test, and I want do this:

testCases := []struct {
    name          string
    testUserID    uint
    expected      User // <- maybe nil
    expectedError error
}

Because the return values of tested function is *User, error.

User is like this, it is defined as DB scheme.

type User struct {
  ID uint
  CreatedAt time.Time
  UpdatedAt time.Time
  ...
}

But in this case, I cannot make expected nil.

How can I do this?

Or my approach to do table driven test is wrong?

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Taichi
  • 2,297
  • 6
  • 25
  • 47

4 Answers4

26

For empty field you can check for empty values which is zero value which is not nil in case of struct.

When storage is allocated for a variable, either through a declaration or a call of new, or when a new value is created, either through a composite literal or a call of make, and no explicit initialization is provided, the variable or value is given a default value. Each element of such a variable or value is set to the zero value for its type: false for booleans, 0 for numeric types, "" for strings, and nil for pointers, functions, interfaces, slices, channels, and maps.

In your case are using the Struct not a pointer to struct. The value is not nil it is empty though

var user User
fmt.Println(user == User{}) // will print true

But since in your case the returned value is pointer to struct *User, error you can check for nil

var user *User
fmt.Println(user == nil) // will print true

Create struct field that is a pointer.

testCases := []struct {
    name          string
    testUserID    uint
    expected      *User // <- maybe nil
    expectedError error
}
Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Himanshu
  • 12,071
  • 7
  • 46
  • 61
15

Go basic types have defined zero values and cannot be nil.

If you want a value to be simply nillable, make it a pointer.

If you do not want a pointer behaviour, you can use null types from third party packages,

e.g. https://github.com/guregu/null

for example int is implemented as:

type Int struct {
    Int   int
    Valid bool
}

another solution is to write your own struct with nullable value

  • 10
    Is there any standard for this, or at least official go draft, or issue opened? It's quite missing feature, there are many cases, where there's need to differentiate between missing value and zero value. E.g. `examResults.Score == 0` (no points), and `examResults.Score == nil` (unknown score). – kravemir Dec 27 '20 at 11:22
10

You can also use special sql type:

type structName struct {
    id sql.NullInt64
    name sql.NullString
    field sql.NullBool
}
Egor Matveev
  • 101
  • 1
  • 2
2

also you can use any, and will accept any value.

testCases := []struct {
    name          string
    testUserID    uint
    expected      any
    expectedError error
}
Fernando Aguirre
  • 1,346
  • 1
  • 9
  • 7