<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/the-test-pyramid-is-a-lie-and-what-i-do-instead--ak2scchgz" -->

---
title: The Test Pyramid Is a Lie (and What I Do Instead)
description: The classic test pyramid — lots of unit tests, few integration tests — was practical advice for 2009 when spinning up real databases was slow and expensive....
canonical: https://daily.dev/posts/the-test-pyramid-is-a-lie-and-what-i-do-instead--ak2scchgz
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: The Test Pyramid Is a Lie (and What I Do Instead) | daily.dev
og:description: The classic test pyramid — lots of unit tests, few integration tests — was practical advice for 2009 when spinning up real databases was slow and expensive....
og:url: https://daily.dev/posts/the-test-pyramid-is-a-lie-and-what-i-do-instead--ak2scchgz
og:image: https://api.daily.dev/og/posts/ak2scCHgZ.png
og:image:alt: The Test Pyramid Is a Lie (and What I Do Instead)
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# The Test Pyramid Is a Lie (and What I Do Instead)

**[Milan Jovanović](https://daily.dev/sources/milanjovanovic)** · 6 min read · 40 upvotes · 0 comments

## Summary

The classic test pyramid — lots of unit tests, few integration tests — was practical advice for 2009 when spinning up real databases was slow and expensive. With Testcontainers and .NET Aspire, that constraint is gone. The author argues that most real bugs live at the seams (handlers, repositories, HTTP endpoints), where unit tests with mocks fail to catch them. The proposed alternative is a 'testing trophy' shape: a thin base of unit tests for pure domain logic (~15-25%), a thick middle of integration tests against real PostgreSQL/RabbitMQ/Redis (~60-70%), a small cap of E2E tests for critical flows (<10%), and architecture/contract tests as a foundation layer. A concrete example shows how a missing SaveChangesAsync call — undetected by 94% unit test coverage — would have been caught immediately by a single integration test.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://www.milanjovanovic.tech/blog/the-test-pyramid-is-a-lie-and-what-i-do-instead>

## Similar posts on daily.dev

- [Medium](https://daily.dev/posts/medium-vglich5gj) · Medium · 0 upvotes · 0 comments
- [How to Test Vertical Slice Architecture](https://daily.dev/posts/how-to-test-vertical-slice-architecture-j5kybyrnx) · Milan Jovanović · 7 upvotes · 0 comments

---

Tags: [#testing](https://daily.dev/tags/testing), [#.net](https://daily.dev/tags/.net)

[View this post on daily.dev](https://daily.dev/posts/the-test-pyramid-is-a-lie-and-what-i-do-instead--ak2scchgz)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"The Test Pyramid Is a Lie (and What I Do Instead)","url":"https://daily.dev/posts/the-test-pyramid-is-a-lie-and-what-i-do-instead--ak2scchgz","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/the-test-pyramid-is-a-lie-and-what-i-do-instead--ak2scchgz"},"datePublished":"2026-04-24T19:44:32.199Z","dateModified":"2026-04-24T19:44:55.549Z","description":"The classic test pyramid — lots of unit tests, few integration tests — was practical advice for 2009 when spinning up real databases was slow and expensive....","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/d7e8bc18116c580dd3a11e4d96c203a8?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/d7e8bc18116c580dd3a11e4d96c203a8?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"Milan Jovanović","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Milan Jovanović","logo":"https://media.daily.dev/image/upload/t_logo,f_auto/v1/logos/78d8abfb692746538410dee47f93e566","url":"https://daily.dev/sources/milanjovanovic"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/the-test-pyramid-is-a-lie-and-what-i-do-instead--ak2scchgz","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":40},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"testing,.net","timeRequired":"PT6M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Milan Jovanović","item":"https://daily.dev/sources/milanjovanovic"},{"@type":"ListItem","position":3,"name":"The Test Pyramid Is a Lie (and What I Do Instead)"}]}
```

