Skip to content

Deep Dive: Mocking & Assertions ​

In traditional frameworks, the hardest part of testing isn't writing the assertions—it is managing the environment. You spend hours writing teardown scripts to clean up database rows, and you use brittle libraries like jest.mock() to stop your tests from accidentally charging real credit cards.

Carotene eliminates environment management entirely. Every test block executes inside a Vapor Sandbox—a completely blank, in-memory universe that exists only for the millisecond that specific test runs.

To manipulate this sandbox, Carotene gives you two incredibly powerful, native primitives: mock and asserts.

1. The mock Keyword (Controlling Reality) ​

The mock keyword is your god-mode inside the test sandbox. It allows you to artificially construct database state and intercept external network boundaries without writing a single line of setup/teardown boilerplate.

Mocking Database State (Dual-Binding) ​

When you want to seed the test database, you do not use .create() or .insert(). Those imply permanent disk writes. Instead, you mock the record.

dart
// 1. Injects the record into the Sandbox DB.
// 2. Binds the strongly-typed object to the 'vipUser' variable.
vipUser = mock store.User { 
  id: "user_1", 
  role: "Admin", 
  email: "admin@corp.com" 
}

// You can now safely pass that variable directly into other mocks or functions
targetOrder = mock store.Order {
  id: "ord_1",
  userId: vipUser.id // Relational binding is effortless
}

Mocking External Integrations (Network Interception) ​

If your architecture blueprint includes a calls integration... verb, Carotene knows exactly where the network boundary is.

If you do not mock a declared integration, the test will automatically fail (to protect you from accidental real-world API calls). You use mock to intercept the call and instantly return a fake Future resolution.

dart
// Intercept the Stripe call and force it to return a successful transaction ID
mock integration.Stripe.ChargeCustomer -> "txn_998877"

// Force a network failure to test your Sad Path logic
mock integration.Stripe.ChargeCustomer -> throws "Insufficient Funds"

2. The asserts Keyword (Proving the Blueprint) ​

Once you trigger your standard function call (e.g., ProcessRefund(targetOrder.id)), you use asserts to verify that the AI correctly mutated the sandbox and triggered the right side-effects.

Asserting Database Mutations ​

You can directly query the sandbox store to ensure the AI's logic resulted in the correct permanent state changes.

dart
ProcessCheckout(targetOrder.id)

// Verify the status was updated
asserts store.Order(targetOrder.id).status == Paid

// Verify the AI did the math correctly
asserts store.Order(targetOrder.id).total == 150.00

Asserting Side-Effects (The Network Graph) ​

Sometimes a function doesn't change the database; it just sends an email or fires a webhook. Carotene tracks every single boundary crossing in the sandbox, allowing you to assert exactly what left the system.

dart
ProcessCheckout(targetOrder.id)

// Verify the integration was hit with the exact expected payload
asserts integration.SendGrid.SendReceipt.wasCalledWith("admin@corp.com")

// Asserting the Negative: Prove the AI didn't hallucinate an email to the wrong person
asserts integration.SendGrid.SendAlert.wasNotCalled()

Asserting Errors and Rejections ​

Testing that your system correctly rejects bad data is just as important as testing the happy path. If your architecture includes strict rules (e.g., rejects with "Refund Expired"), you can assert that the function call itself fails.

dart
test "Rejects orders older than 30 days" {
  oldOrder = mock store.Order { id: "ord_99", ageInDays: 45 }
  
  // The assertion wraps the function execution to catch the rejection
  asserts ProcessRefund(oldOrder.id) fails with "Refund Expired"
  
  // Prove that because it failed, no side-effects leaked out
  asserts integration.Stripe.RefundPayment.wasNotCalled()
}

3. Putting it all together (The Complete Test Matrix) ​

Because Carotene's test syntax is so flat and declarative, you can easily read a test from top to bottom and understand exactly what business rule is being enforced.

dart
domain Commerce {
  
  test "Applies VIP discount and successfully charges card" {
    
    // 1. Mock the Environment
    vipUser = mock store.User { id: "user_1", role: "VIP" }
    cart = mock store.Cart { id: "cart_1", userId: vipUser.id, subtotal: 100.0 }
    
    mock integration.Stripe.ChargeCustomer -> true

    // 2. Execute the Logic
    ProcessCheckout(cart.id)

    // 3. Assert the Outcomes
    // VIPs get 20% off. The AI must calculate 80.0, or the build fails.
    asserts integration.Stripe.ChargeCustomer.wasCalledWith(80.0)
    
    // The cart should be converted to an order
    asserts store.Order(userId: vipUser.id).exists()
    asserts store.Cart("cart_1").status == Converted
  }
}

By decoupling the data setup from the hard drive, and the network setup from the internet, Carotene's mock and assertsprimitives allow you to mathematically prove your generative logic in absolute safety.