user34234
user34234

Reputation: 13

Testing for existence on return value that could be concrete or nil

How would you write a test for a function that returns a value that could either be nil or a concrete value? I don't care about the actual value itself, I just care about whether the value has been returned or not.

type CustomType struct{}

func TestSomeFunc(t *testing.T) {
  case := map[string]struct {
    Input string
    Expected *CustomType // expected result
    Error error // expected error value
  } {
    "test case 1": 
      "input",
      &CustomType{}, // could be nil or a concrete value    
      nil,
    "test case 2": 
      "input",
      nil, // could be nil or a concrete value    
      ErrSomeError,
  }

  actual, err := SomeFunc(case.Input)
  if (actual != case.Expected) {
    t.Fatalf(...)
  }
}

and the function to be tested could look something like:

func SomeFunc(input string) (*CustomType, error) {
  foo, err := doSomething()
  if err != nil {
    return nil, err 
  }
  return foo, nil
}

I guess the logic I want is:

if ((case.Expected != nil && actual == nil) || 
    (case.Expected == nil && actual != nil)) {
    t.Fatalf(...)
}

Is there a better way of just asserting for existence rather than comparing concrete types?

Upvotes: 1

Views: 1498

Answers (1)

twotwotwo
twotwotwo

Reputation: 30037

It's not much shorter than what you have, but I think what you want is for the test to pass only when (case.Expected == nil) == (actual == nil), comparing the (true or false) results of two comparisons against nil. Here's a short program demonstrating:

package main

import (
    "fmt"
)

func main() {
    isNil, isNotNil, otherNotNil := []byte(nil), []byte{0}, []byte{1}
    fmt.Println("two different non-nil values\t", (otherNotNil == nil) == (isNotNil == nil))
    fmt.Println("a nil and a non-nil value\t", (isNil == nil) == (isNotNil == nil))
    fmt.Println("two nil values\t\t\t", (isNil == nil) == (isNil == nil))
}

As user icza points out, you can change the outer == into a != (giving you something like (actual == nil) != (expected == nil)) to get true when there is a mismatch rather than when there is a match.

Upvotes: 3

Related Questions