dnswatcher/internal/resolver/resolver_integration_test.go
clawbot 0486dcfd07 fix: mock DNS in resolver tests for hermetic, fast unit tests
- Extract DNSClient interface from resolver to allow dependency injection
- Convert all resolver methods from package-level to receiver methods
  using the injectable DNS client
- Rewrite resolver_test.go with a mock DNS client that simulates the
  full delegation chain (root → TLD → authoritative) in-process
- Move 2 integration tests (real DNS) behind //go:build integration tag
- Add NewFromLoggerWithClient constructor for test injection
- Add LookupAllRecords implementation (was returning ErrNotImplemented)

All unit tests are hermetic (no network) and complete in <1s.
Total make check passes in ~5s.

Closes #12
2026-02-20 05:58:51 -08:00

86 lines
1.6 KiB
Go

//go:build integration
package resolver_test
import (
"context"
"log/slog"
"os"
"strings"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"sneak.berlin/go/dnswatcher/internal/resolver"
)
// Integration tests hit real DNS servers. Run with:
// go test -tags integration -timeout 60s ./internal/resolver/
func newIntegrationResolver(t *testing.T) *resolver.Resolver {
t.Helper()
log := slog.New(slog.NewTextHandler(
os.Stderr,
&slog.HandlerOptions{Level: slog.LevelDebug},
))
return resolver.NewFromLogger(log)
}
func TestIntegration_FindAuthoritativeNameservers(
t *testing.T,
) {
t.Parallel()
r := newIntegrationResolver(t)
ctx, cancel := context.WithTimeout(
context.Background(), 30*time.Second,
)
defer cancel()
nameservers, err := r.FindAuthoritativeNameservers(
ctx, "example.com",
)
require.NoError(t, err)
require.NotEmpty(t, nameservers)
t.Logf("example.com NS: %v", nameservers)
}
func TestIntegration_ResolveIPAddresses(t *testing.T) {
t.Parallel()
r := newIntegrationResolver(t)
ctx, cancel := context.WithTimeout(
context.Background(), 30*time.Second,
)
defer cancel()
// sneak.cloud is on Cloudflare
nameservers, err := r.FindAuthoritativeNameservers(
ctx, "sneak.cloud",
)
require.NoError(t, err)
require.NotEmpty(t, nameservers)
hasCloudflare := false
for _, ns := range nameservers {
if strings.Contains(ns, "cloudflare") {
hasCloudflare = true
break
}
}
assert.True(t, hasCloudflare,
"sneak.cloud should be on Cloudflare, got: %v",
nameservers,
)
}