---
status: pending
priority: p1
issue_id: "008"
tags: [testing, architecture, refactoring, vendors, best-practices]
dependencies: []
---

# Refactor Tests to Focus on Behavior vs Implementation Details

## Problem Statement

The vendors test file tests internal implementation functions (`fetch-ids`, `hydrate-results`) rather than the public interface (`fetch-page`). This creates:
1. Brittle tests that break during refactoring
2. Tight coupling to internal structure
3. Violation of "Test user-observable behavior" principle

## Findings

**From architecture-strategist and kieran-rails-reviewer:**

**Tests exercising internal functions (lines 47, 80, 170):**
```clojure
;; Testing internal implementation
(sut/fetch-ids db {:query-params ...})      ; Internal query helper
(sut/hydrate-results [vendor-id] db {})     ; Internal hydration helper
```

**Problem:** These are intermediate functions used by `fetch-page`. Testing them directly:
- Couples tests to implementation details
- Makes refactoring harder (changing internal structure breaks tests)
- Violates testing conventions from AGENTS.md

**accounts_test.clj pattern - tests public interface:**
```clojure
;; Tests public behavior through account-save and fetch-page
(let [result (sut/account-save {:form-params ...})]
  (is (= 200 (:status result))))

(let [[accounts matching-count] (sut/fetch-page {:query-params ...})]
  (is (number? matching-count)))
```

## Proposed Solutions

### Option A: Remove Implementation Detail Tests (Recommended)
**Effort:** Small (15 minutes)
**Risk:** Low

Remove or refactor tests that directly test `fetch-ids` and `hydrate-results`:

1. **Remove:** `vendor-fetch-ids-returns-correct-structure` (lines 40-53)
   - Already covered by `vendor-fetch-page-returns-vendors`
   - Tests same functionality through public interface

2. **Remove:** `vendor-hydrate-results-works` (lines 71-86)
   - Merge into `vendor-fetch-page-returns-vendors`
   - Test hydration through `fetch-page` output

3. **Keep:** `vendor-hydration-includes-all-fields` (lines 158-177)
   - Rename to `vendor-fetch-page-returns-complete-vendor-data`
   - Test through `fetch-page` instead of `hydrate-results`

**Pros:**
- Follows accounts_test.clj pattern
- Tests are more resilient to refactoring
- Focuses on user-observable behavior
- Reduces test file size (~40 lines)

**Cons:**
- Slightly less granular test coverage
- May miss edge cases in internal functions

### Option B: Make Functions Private
**Effort:** Small (10 minutes)
**Risk:** Medium

Change `fetch-ids` and `hydrate-results` to private (`defn-`):
```clojure
(defn- fetch-ids [db request] ...)
(defn- hydrate-results [ids db _] ...)
```

Then test through `fetch-page`:
```clojure
(deftest vendor-fetch-page-works
  (let [[vendors count] (sut/fetch-page request)]
    ;; This implicitly tests fetch-ids and hydrate-results
    ...))
```

**Pros:**
- Clearly signals these are implementation details
- Forces tests to use public interface

**Cons:**
- Requires modifying source file (vendors.clj)
- May break other code using these functions
- Risk of breaking changes

### Option C: Extract to Query Namespace
**Effort:** Medium (1 hour)
**Risk:** Medium

Create `auto-ap.queries.vendor` namespace:
```clojure
(ns auto-ap.queries.vendor
  (:require [datomic.api :as dc]))

(defn fetch-ids [db query-params] ...)
(defn hydrate-results [ids db] ...)
```

Test in separate file with explicit contract tests.

**Pros:**
- Clear separation of concerns
- Query functions become public API of new namespace
- Follows single responsibility principle

**Cons:**
- Significant refactoring
- Requires updating all callers
- Overkill for current scope

## Recommended Action

**Go with Option A** - remove implementation detail tests and focus on behavior:

1. Delete `vendor-fetch-ids-returns-correct-structure` (covered by fetch-page test)
2. Delete `vendor-hydrate-results-works` (merge into fetch-page test)
3. Refactor `vendor-hydration-includes-all-fields` to use `fetch-page`

This aligns with:
- accounts_test.clj pattern
- testing-conventions skill guidelines
- "Test behavior, not implementation" principle

## Technical Details

**Affected Files:**
- `test/clj/auto_ap/ssr/admin/vendors_test.clj`

**Tests to Remove/Refactor:**
- Lines 40-53: `vendor-fetch-ids-returns-correct-structure` → REMOVE
- Lines 71-86: `vendor-hydrate-results-works` → REMOVE (merge assertions into fetch-page test)
- Lines 158-177: `vendor-hydration-includes-all-fields` → REFACTOR to use fetch-page

**Verification:**
```bash
lein test auto-ap.ssr.admin.vendors-test  # All tests pass
lein cljfmt check                         # Formatting correct
```

## Acceptance Criteria

- [ ] `vendor-fetch-ids-returns-correct-structure` removed
- [ ] `vendor-hydrate-results-works` removed (assertions merged)
- [ ] `vendor-hydration-includes-all-fields` refactored to test through `fetch-page`
- [ ] Remaining tests focus on public interface (`fetch-page`, `merge-submit`)
- [ ] Tests still pass
- [ ] Code formatted with lein cljfmt

## Work Log

### 2026-02-07 - Initial Creation

**By:** Architecture Strategist Agent

**Actions:**
- Identified implementation detail testing pattern
- Compared with accounts_test.clj public interface approach
- Created todo with multiple solution options

**Learnings:**
- testing-conventions skill emphasizes testing behavior not implementation
- accounts_test.clj only tests public functions (account-save, fetch-page)
- Internal function testing creates maintenance burden
