The types package defines the core type definitions and interfaces for Gomega. It provides the foundational contracts that enable Gomega's matcher system and assertion DSL.
The types package contains:
Understanding these types is essential for:
{ .api }
type GomegaMatcher interface {
Match(actual any) (success bool, err error)
FailureMessage(actual any) (message string)
NegatedFailureMessage(actual any) (message string)
}The fundamental interface that all Gomega matchers must implement.
Methods:
Match(actual any) (success bool, err error)
actual - The value to match againstsuccess - true if match succeeds, false otherwiseerr - Optional error for unexpected conditions (type mismatches, etc.)FailureMessage(actual any) string
Expect(x).To(matcher) failsNegatedFailureMessage(actual any) string
Expect(x).NotTo(matcher) failsExample Implementation:
type evenMatcher struct{}
func (m *evenMatcher) Match(actual any) (bool, error) {
num, ok := actual.(int)
if !ok {
return false, fmt.Errorf("EvenMatcher expects an int, got %T", actual)
}
return num%2 == 0, nil
}
func (m *evenMatcher) FailureMessage(actual any) string {
return fmt.Sprintf("Expected %v to be even", actual)
}
func (m *evenMatcher) NegatedFailureMessage(actual any) string {
return fmt.Sprintf("Expected %v not to be even", actual)
}
// Usage
func BeEven() types.GomegaMatcher {
return &evenMatcher{}
}
Expect(4).To(BeEven())
Expect(7).NotTo(BeEven()){ .api }
type Assertion interface {
Should(matcher GomegaMatcher, optionalDescription ...any) bool
ShouldNot(matcher GomegaMatcher, optionalDescription ...any) bool
To(matcher GomegaMatcher, optionalDescription ...any) bool
ToNot(matcher GomegaMatcher, optionalDescription ...any) bool
NotTo(matcher GomegaMatcher, optionalDescription ...any) bool
}Interface for synchronous assertions returned by Expect().
Methods:
All methods perform an assertion and trigger the fail handler on failure:
Should(matcher GomegaMatcher, optionalDescription ...any) bool
true if successful, false if not (in intercepted mode)ShouldNot(matcher GomegaMatcher, optionalDescription ...any) bool
true if successful, false if notTo(matcher GomegaMatcher, optionalDescription ...any) bool
Should - more readable in some contextsShouldToNot(matcher GomegaMatcher, optionalDescription ...any) bool
ShouldNotNotToNotTo(matcher GomegaMatcher, optionalDescription ...any) bool
ShouldNotToNot by conventionParameters:
matcher - The matcher to applyoptionalDescription - Optional description for the assertion (format string + args)Example Usage:
assertion := Expect(42)
// All of these work
assertion.Should(Equal(42))
assertion.To(Equal(42)) // Same as Should
assertion.ShouldNot(Equal(0))
assertion.NotTo(Equal(0)) // Same as ShouldNot
assertion.ToNot(Equal(0)) // Less common, but valid
// With optional description
Expect(value).To(Equal(100), "checking initial value")
Expect(count).To(BeNumerically(">", 0), "count should be positive: %d", count){ .api }
type AsyncAssertion interface {
Should(matcher GomegaMatcher, optionalDescription ...any) bool
ShouldNot(matcher GomegaMatcher, optionalDescription ...any) bool
Within(timeout time.Duration) AsyncAssertion
WithTimeout(timeout time.Duration) AsyncAssertion
WithPolling(interval time.Duration) AsyncAssertion
WithContext(ctx context.Context) AsyncAssertion
WithArguments(args ...any) AsyncAssertion
MustPassRepeatedly(count int) AsyncAssertion
ProbeEvery(interval time.Duration) AsyncAssertion
}Interface for asynchronous assertions returned by Eventually() and Consistently().
Assertion Methods:
Should(matcher GomegaMatcher, optionalDescription ...any) bool
Eventually: succeeds when matcher passes onceConsistently: fails if matcher ever failsShouldNot(matcher GomegaMatcher, optionalDescription ...any) bool
Eventually: succeeds when matcher fails onceConsistently: fails if matcher ever passesConfiguration Methods:
All configuration methods return the AsyncAssertion for chaining.
Within(timeout time.Duration) AsyncAssertion
WithTimeoutWithTimeout(timeout time.Duration) AsyncAssertion
Eventually: maximum time to wait for successConsistently: duration to maintain consistencyWithPolling(interval time.Duration) AsyncAssertion
ProbeEveryWithContext(ctx context.Context) AsyncAssertion
WithArguments(args ...any) AsyncAssertion
func(args...) TMustPassRepeatedly(count int) AsyncAssertion
Eventually: matcher must pass count times in a rowProbeEvery(interval time.Duration) AsyncAssertion
WithPollingExample Usage:
// Basic Eventually
Eventually(func() int { return counter }).Should(Equal(10))
// With timeout and polling
Eventually(func() bool {
return server.IsReady()
}, "30s", "1s").Should(BeTrue())
// Fluent configuration
Eventually(getStatus).
WithTimeout(30 * time.Second).
WithPolling(500 * time.Millisecond).
Should(Equal("ready"))
// With context
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
Eventually(checkHealth).
WithContext(ctx).
Should(Succeed())
// Must pass repeatedly (prevent flakes)
Eventually(func() bool {
return service.Check()
}).
WithTimeout(10 * time.Second).
MustPassRepeatedly(3).
Should(BeTrue())
// Consistently - must remain true
Consistently(func() int {
return activeConnections
}, "5s", "500ms").Should(BeNumerically("<=", 100)){ .api }
type Gomega interface {
Ω(actual any, extra ...any) Assertion
Expect(actual any, extra ...any) Assertion
ExpectWithOffset(offset int, actual any, extra ...any) Assertion
Eventually(actualOrCtx any, args ...any) AsyncAssertion
EventuallyWithOffset(offset int, actualOrCtx any, args ...any) AsyncAssertion
Consistently(actualOrCtx any, args ...any) AsyncAssertion
ConsistentlyWithOffset(offset int, actualOrCtx any, args ...any) AsyncAssertion
SetDefaultEventuallyTimeout(time.Duration)
SetDefaultEventuallyPollingInterval(time.Duration)
SetDefaultConsistentlyDuration(time.Duration)
SetDefaultConsistentlyPollingInterval(time.Duration)
}The main Gomega interface that defines the complete assertion DSL.
Synchronous Assertion Methods:
Ω(actual any, extra ...any) Assertion
Expect)Expect(actual any, extra ...any) Assertion
ExpectWithOffset(offset int, actual any, extra ...any) Assertion
Expect but adjusts call stack offset for error reportingAsynchronous Assertion Methods:
Eventually(actualOrCtx any, args ...any) AsyncAssertion
EventuallyWithOffset(offset int, actualOrCtx any, args ...any) AsyncAssertion
Eventually with custom stack offsetConsistently(actualOrCtx any, args ...any) AsyncAssertion
ConsistentlyWithOffset(offset int, actualOrCtx any, args ...any) AsyncAssertion
Consistently with custom stack offsetConfiguration Methods:
SetDefaultEventuallyTimeout(time.Duration)
Eventually callsSetDefaultEventuallyPollingInterval(time.Duration)
EventuallySetDefaultConsistentlyDuration(time.Duration)
ConsistentlySetDefaultConsistentlyPollingInterval(time.Duration)
ConsistentlyExample Usage:
// Creating custom Gomega instance
gomega := NewGomega(func(message string, callerSkip ...int) {
// Custom fail handler
fmt.Printf("Test failed: %s\n", message)
})
// Using the instance
gomega.Expect(42).To(Equal(42))
gomega.Eventually(func() int { return counter }).Should(Equal(10))
// Configure defaults
gomega.SetDefaultEventuallyTimeout(30 * time.Second)
gomega.SetDefaultEventuallyPollingInterval(500 * time.Millisecond){ .api }
type GomegaFailHandler func(message string, callerSkip ...int)Function type for handling test failures. This is the bridge between Gomega and your test framework.
Parameters:
message - The failure message to reportcallerSkip - Optional call stack skip count for proper error location reportingExample Implementations:
// For Ginkgo
func GinkgoFailHandler(message string, callerSkip ...int) {
Fail(message, callerSkip...)
}
// For testing.T
func TestingTFailHandler(t *testing.T) GomegaFailHandler {
return func(message string, callerSkip ...int) {
t.Helper()
t.Fatalf("\n%s", message)
}
}
// Custom handler
func CustomFailHandler(message string, callerSkip ...int) {
log.Printf("Assertion failed: %s", message)
os.Exit(1)
}
// Usage
RegisterFailHandler(GinkgoFailHandler)
// or
gomega := NewGomega(TestingTFailHandler(t)){ .api }
type GomegaTestingT interface {
Helper()
Fatalf(format string, args ...any)
}Interface compatible with *testing.T for integration with Go's standard testing package.
Methods:
Helper()
Fatalf(format string, args ...any)
Printf followed by FailNowExample Usage:
func TestMyFunction(t *testing.T) {
// NewWithT creates a Gomega instance bound to testing.T
g := NewWithT(t)
result := MyFunction()
g.Expect(result).To(Equal(42))
// Can also use package-level with RegisterTestingT
RegisterTestingT(t)
Expect(result).To(Equal(42))
}package custommatchers
import (
"fmt"
"github.com/onsi/gomega/types"
)
// CustomMatcher implementation
type stringLengthMatcher struct {
minLength int
maxLength int
}
func (m *stringLengthMatcher) Match(actual any) (bool, error) {
str, ok := actual.(string)
if !ok {
return false, fmt.Errorf("StringLengthMatcher expects a string, got %T", actual)
}
length := len(str)
return length >= m.minLength && length <= m.maxLength, nil
}
func (m *stringLengthMatcher) FailureMessage(actual any) string {
str := actual.(string)
return fmt.Sprintf(
"Expected string '%s' (length %d) to have length between %d and %d",
str, len(str), m.minLength, m.maxLength,
)
}
func (m *stringLengthMatcher) NegatedFailureMessage(actual any) string {
str := actual.(string)
return fmt.Sprintf(
"Expected string '%s' (length %d) not to have length between %d and %d",
str, len(str), m.minLength, m.maxLength,
)
}
// Matcher factory function
func HaveStringLength(min, max int) types.GomegaMatcher {
return &stringLengthMatcher{
minLength: min,
maxLength: max,
}
}
// Usage
var _ = Describe("Custom Matcher", func() {
It("validates string length", func() {
Expect("hello").To(HaveStringLength(3, 10))
Expect("hi").NotTo(HaveStringLength(5, 10))
})
})package mytest
import (
"testing"
"github.com/onsi/gomega"
"github.com/onsi/gomega/types"
)
func TestWithCustomGomega(t *testing.T) {
// Create custom fail handler
failures := []string{}
customHandler := func(message string, callerSkip ...int) {
failures = append(failures, message)
}
// Create Gomega instance with custom handler
g := gomega.NewGomega(customHandler)
// Use the instance
g.Expect(1).To(gomega.Equal(2)) // Captures failure instead of failing
g.Expect(3).To(gomega.Equal(4)) // Captures another failure
// Check captured failures
if len(failures) != 2 {
t.Fatalf("Expected 2 failures, got %d", len(failures))
}
}package mypackage_test
import (
"testing"
. "github.com/onsi/gomega"
)
func TestWithTestingT(t *testing.T) {
// Method 1: NewWithT (recommended)
g := NewWithT(t)
result := processData("input")
g.Expect(result).To(Equal("expected"))
g.Eventually(func() bool {
return isReady()
}).Should(BeTrue())
// Method 2: Package-level (legacy)
RegisterTestingT(t)
Expect(result).To(Equal("expected"))
}
func TestTableDriven(t *testing.T) {
tests := []struct {
name string
input string
expected string
}{
{"case1", "input1", "output1"},
{"case2", "input2", "output2"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
g := NewWithT(t)
result := processData(tt.input)
g.Expect(result).To(Equal(tt.expected))
})
}
}package helpers
import (
. "github.com/onsi/gomega"
"github.com/onsi/gomega/types"
)
// Helper function that wraps Expect
func ExpectValid(obj interface{}) types.Assertion {
// Use offset of 1 so errors point to the caller
return ExpectWithOffset(1, obj)
}
func ExpectStatusOK(response *http.Response) {
// Offset ensures error points to test code, not this helper
ExpectWithOffset(1, response.StatusCode).To(Equal(200))
}
// Usage in tests
var _ = Describe("Using Helpers", func() {
It("uses helper functions", func() {
obj := CreateObject()
ExpectValid(obj).To(BeTrue()) // Error points here, not to helper
resp := MakeRequest()
ExpectStatusOK(resp) // Error points here
})
})package matchers
import (
"fmt"
"github.com/onsi/gomega/types"
)
// Matcher that combines multiple matchers
type allOfMatcher struct {
matchers []types.GomegaMatcher
}
func (m *allOfMatcher) Match(actual any) (bool, error) {
for _, matcher := range m.matchers {
success, err := matcher.Match(actual)
if err != nil {
return false, err
}
if !success {
return false, nil
}
}
return true, nil
}
func (m *allOfMatcher) FailureMessage(actual any) string {
messages := []string{}
for _, matcher := range m.matchers {
success, _ := matcher.Match(actual)
if !success {
messages = append(messages, matcher.FailureMessage(actual))
}
}
return fmt.Sprintf("Expected all matchers to pass:\n%s", strings.Join(messages, "\n"))
}
func (m *allOfMatcher) NegatedFailureMessage(actual any) string {
return fmt.Sprintf("Expected at least one matcher to fail")
}
func AllOf(matchers ...types.GomegaMatcher) types.GomegaMatcher {
return &allOfMatcher{matchers: matchers}
}
// Usage
Expect(value).To(AllOf(
BeNumerically(">", 0),
BeNumerically("<", 100),
Not(Equal(50)),
))type eventuallyTrueMatcher struct {
checks int
}
func (m *eventuallyTrueMatcher) Match(actual any) (bool, error) {
m.checks++
fn, ok := actual.(func() bool)
if !ok {
return false, fmt.Errorf("Expected a func() bool, got %T", actual)
}
return fn(), nil
}
func (m *eventuallyTrueMatcher) FailureMessage(actual any) string {
return fmt.Sprintf("Expected function to return true (checked %d times)", m.checks)
}
func (m *eventuallyTrueMatcher) NegatedFailureMessage(actual any) string {
return fmt.Sprintf("Expected function not to return true")
}
func EventuallyTrue() types.GomegaMatcher {
return &eventuallyTrueMatcher{}
}
// Usage
counter := 0
Eventually(func() bool {
counter++
return counter > 5
}).Should(EventuallyTrue())type errorChainMatcher struct {
target error
}
func (m *errorChainMatcher) Match(actual any) (bool, error) {
err, ok := actual.(error)
if !ok {
return false, fmt.Errorf("Expected an error, got %T", actual)
}
if err == nil {
return false, nil
}
// Check if target is in error chain
return errors.Is(err, m.target), nil
}
func (m *errorChainMatcher) FailureMessage(actual any) string {
if actual == nil {
return fmt.Sprintf("Expected error chain to contain %v, but got nil", m.target)
}
return fmt.Sprintf("Expected error chain %v to contain %v", actual, m.target)
}
func (m *errorChainMatcher) NegatedFailureMessage(actual any) string {
return fmt.Sprintf("Expected error chain %v not to contain %v", actual, m.target)
}
func ContainError(target error) types.GomegaMatcher {
return &errorChainMatcher{target: target}
}
// Usage
var ErrNotFound = errors.New("not found")
err := someFunction()
Expect(err).To(ContainError(ErrNotFound))Use built-in matchers when possible:
// Good: Use built-in
Expect(slice).To(ContainElement("item"))
// Unnecessary: Custom matcher for standard case
// (Unless you have specific requirements)Handle type mismatches gracefully:
func (m *myMatcher) Match(actual any) (bool, error) {
value, ok := actual.(MyType)
if !ok {
return false, fmt.Errorf("Expected MyType, got %T", actual)
}
// ... matching logic
}Provide informative failure messages:
func (m *myMatcher) FailureMessage(actual any) string {
// Good: Specific and actionable
return fmt.Sprintf(
"Expected value %v to be in range [%d, %d], but it was outside",
actual, m.min, m.max,
)
// Avoid: Vague
// return "Match failed"
}Maintain correct error locations:
func ExpectHTTPSuccess(resp *http.Response) {
// Offset 1: error reports at caller
ExpectWithOffset(1, resp.StatusCode).To(BeNumerically("<", 400))
}Ensure matchers are safe for concurrent use:
// Good: No shared mutable state
type safeMatcher struct {
expected int // immutable after creation
}
// Avoid: Mutable state
type unsafeMatcher struct {
counter int // modified during Match
}Return errors for truly exceptional conditions:
func (m *myMatcher) Match(actual any) (bool, error) {
// Type mismatch: return error
if _, ok := actual.(string); !ok {
return false, fmt.Errorf("wrong type")
}
// Match failure: return false, nil
if !condition {
return false, nil
}
return true, nil
}GomegaMatcher (implemented by all matchers)
├─ Match() - performs matching
├─ FailureMessage() - formats failure
└─ NegatedFailureMessage() - formats negated failure
Assertion (returned by Expect)
├─ Should() / To()
├─ ShouldNot() / NotTo()
└─ Uses GomegaMatcher
AsyncAssertion (returned by Eventually/Consistently)
├─ Should() / ShouldNot()
├─ Configuration methods
└─ Uses GomegaMatcher
Gomega (main interface)
├─ Expect() → Assertion
├─ Eventually() → AsyncAssertion
├─ Consistently() → AsyncAssertion
└─ Configuration methods
GomegaFailHandler (fail handler function)
└─ Called when assertions fail
GomegaTestingT (testing.T interface)
└─ Enables integration with testing packageGomega also provides type aliases in the main package:
type Gomega = types.Gomega
type Assertion = types.Assertion
type AsyncAssertion = types.AsyncAssertion
type GomegaMatcher = types.GomegaMatcher
type GomegaFailHandler = types.GomegaFailHandler
type GomegaTestingT = types.GomegaTestingTThis allows importing from either package:
import "github.com/onsi/gomega/types"
var matcher types.GomegaMatcher
// Or
import "github.com/onsi/gomega"
var matcher gomega.GomegaMatcher