Я боровся з все більш набридливою проблемою щодо наших тестових підрозділів, які ми впроваджуємо в своїй команді. Ми намагаємось додати одиничні тести до застарілого коду, який не був добре розроблений, і хоча ми не мали жодних труднощів з фактичним додаванням тестів, ми починаємо боротися з тим, як виходять тести.
Як приклад проблеми, скажімо, у вас є метод, який викликає 5 інших методів як частину його виконання. Тестом цього методу може бути підтвердження того, що поведінка виникає в результаті викликання одного з цих 5 інших методів. Отже, оскільки тест одиниці повинен провалюватися лише з однієї причини та однієї причини, ви хочете усунути потенційні проблеми, викликані викликом цих інших 4-х методів, і знущатися над ними. Чудово! Виконання одиничного тесту, знущаються методи ігноруються (і їх поведінку можна підтвердити як частина інших тестів одиниці), і перевірка працює.
Але є нова проблема - блок-тест має інтимні знання про те, як ви підтвердили, що поведінка та будь-яка підпис змінюється на будь-який із цих 4-х методів у майбутньому чи будь-які нові методи, які потрібно додати до «батьківського методу», в результаті потрібно змінити тест приладу, щоб уникнути можливих збоїв.
Звичайно, проблему можна було б дещо пом'якшити, просто застосувавши більше методів, щоб зменшити поведінку, але я сподівався, що є, можливо, більш елегантне рішення.
Ось приклад тестового блоку, який фіксує проблему.
Як швидка примітка, «MergeTests» - це клас тестування одиниць, який успадковується від класу, який ми тестуємо, і за необхідності переосмислює поведінку. Це "шаблон", який ми використовуємо в наших тестах, щоб ми могли перекрити виклики до зовнішніх класів / залежностей.
[TestMethod]
public void VerifyMergeStopsSpinner()
{
var mockViewModel = new Mock<MergeTests> { CallBase = true };
var mockMergeInfo = new MergeInfo(Mock.Of<IClaim>(), Mock.Of<IClaim>(), It.IsAny<bool>());
mockViewModel.Setup(m => m.ClaimView).Returns(Mock.Of<IClaimView>);
mockViewModel.Setup(
m =>
m.TryMergeClaims(It.IsAny<Func<bool>>(), It.IsAny<IClaim>(), It.IsAny<IClaim>(), It.IsAny<bool>(),
It.IsAny<bool>()));
mockViewModel.Setup(m => m.GetSourceClaimAndTargetClaimByMergeState(It.IsAny<MergeState>())).Returns(mockMergeInfo);
mockViewModel.Setup(m => m.SwitchToOverviewTab());
mockViewModel.Setup(m => m.IncrementSaveRequiredNotification());
mockViewModel.Setup(m => m.OnValidateAndSaveAll(It.IsAny<object>()));
mockViewModel.Setup(m => m.ProcessPendingActions(It.IsAny<string>()));
mockViewModel.Object.OnMerge(It.IsAny<MergeState>());
mockViewModel.Verify(mvm => mvm.StopSpinner(), Times.Once());
}
Як решта з вас впоралися з цим чи не існує чудового "простого" способу поводження з ним?
Оновлення - я ціную відгуки кожного. На жаль, і це не дивно, але, здається, не існує чудового рішення, зразка чи практики, за яким можна перевірити одиничне тестування, якщо код, який тестується, поганий. Я відзначив відповідь, яка найкраще захоплювала цю просту правду.