TGViewer
QA Family by Alexey QA Family by Alexey @dev_qa · 1.63K subscribers
Post #225 1.04K
💻Антипаттерны юнит тестов

Продолжаем тему с юнит тестами, и поговорим какие существуют антипаттерны при написании юнит тестов.

🔎Тестирование приватных методов
У вас есть класс PaymentProcessor, который обрабатывает платежи и содержит приватный метод для валидации транзакций.
class PaymentProcessor {
private validateTransaction(transaction: Transaction): boolean {
// сложная логика
return transaction.amount > 0 && transaction.currency === 'USD';
}

processPayment(transaction: Transaction): string {
if (this.validateTransaction(transaction)) {
return 'Payment processed';
} else {
return 'Invalid transaction';
}
}
}

Антипаттерн:
Делаем метод публичным и тестирование метода validateTransaction напрямую.
Почему это плохо:
✖Нарушает принцип инкапсуляции.
✖Тесты становятся хрупкими при изменении внутренней реализации.
✅Решение:
Тестировать публичный метод processPayment, который использует приватный метод.
Или провести рефакторинг и вынести validateTransaction в отдельный класс.


🔎Раскрытие приватного состояния объекта
Класс Inventory управляет списком товаров на складе.
class Inventory {
private items: Item[] = [];

addItem(item: Item): void {
this.items.push(item);
}
getItems(): ReadonlyArray<Item> {
return this.items;
}

// Другие методы...
}

Антипаттерн:
Чтобы упростить тестирование, приватное свойство items делается публичным.
✅Решение:
Тестировать публичный метод processPayment, который использует приватный метод.


🔎Утечка доменных знаний в тесты
Система рассчитывает налог в зависимости от категории продукта.
class TaxCalculator {
calculateTax(product: Product): number {
if (product.category === 'Food') {
return product.price * 0.05;
} else if (product.category === 'Electronics') {
return product.price * 0.2;
}
return product.price * 0.1;
}
}

Антипаттерн:
Тест дублирует бизнес-логику при расчете ожидаемого результата.
describe('TaxCalculator', () => {
it('should calculate tax for food category', () => {
const calculator = new TaxCalculator();
const product = { price: 100, category: 'Food' };
// тут дублируется логика
const expectedTax = product.price * 0.05;
const tax = calculator.calculateTax(product);
expect(tax).toBe(expectedTax);
});
});

Почему это плохо:
✖Тест повторяет логику, которую должен проверять.
✖При изменении логики необходимо менять и код теста.
✅Решение:
Использовать конкретные значения для ожидаемых результатов.
describe('TaxCalculator', () => {
it('should calculate 5% tax for food category', () => {
const calculator = new TaxCalculator();
const product = { price: 100, category: 'Food' };
const tax = calculator.calculateTax(product);
expect(tax).toBe(5);
});

it('should calculate 20% tax for electronics category', () => {
const calculator = new TaxCalculator();
const product = { price: 200, category: 'Electronics' };
const tax = calculator.calculateTax(product);
expect(tax).toBe(40);
});
});

Теги: #unitTests #cleanСode #TDD #BDD #learning #recommendation #practices
  • 👎 58
  • 👍 7
  • ❤ 3
  • 🔥 2
More from @dev_qa
  1. Sep 23, 2026Следующий спикер митапа Moscow QA #28 x Черный митап +18 Даниил Ахетов с докладом Как я де…
  2. Sep 23, 2026Приходите будет еще Боря, Костя и Саша из PiterQA Все топовые спикеры которые расскажут ве…
  3. Sep 5, 2026Ссылка на трансляцию митапа Moscow QA#27 x Мир Plat.Form: https://vkvideo.ru/video-2052808…
  4. Sep 5, 2026Vitest 5.0 вышел ➖ trace view в Browser Mode: упавший браузерный тест проигрывается по шаг…
  5. Sep 1, 2026Playwright MCP 0.0.80 добавлены инструменты browser_start_recording / browser_stop_recordi…
  6. Aug 26, 2026Post #339
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →