Вы должны позволить вызову M1
пройти к реальному экземпляру метода M2
.
В общем, вы должны проверять поведение черного ящика вашегоклассы.Ваши тесты не должны заботиться о том, чтобы M1
вызывал M2
- это деталь реализации.
Это не то же самое, что насмешливые внешние зависимости (что вы должны сделать) ...
Например, скажем, у меня есть такой класс:
class AccountMerger
{
public AccountMerger(IAccountDao dao)
{
this.dao = dao;
}
public void Merge(Account first, Account second, MergeStrategy strategy)
{
// merge logic goes here...
// [...]
dao.Save(first);
dao.Save(second);
}
public void Merge(Account first, Account second)
{
Merge(first, second, MergeStrategy.Default);
}
private readonly IAccountDao dao;
}
Я хочу, чтобы мои тесты показали, что:
Вызов Merge(first, second, strategy)
приводит к сохранению двух учетных записей, которые были объединены с использованием предоставленного правила.
Вызов Merge(first, second)
приводит к сохранению двух учетных записей, которые были объединены с использованием правила по умолчанию.
Обратите внимание, что оба эти требования сформулированыс точки зрения входных данных и эффектов - в частности, Мне все равно, как класс достигает этих результатов, пока он .
Тот факт, что второй метод использует первый, не является чем-то, что меня волнует, или даже тем, что я хочу применить - если я это сделаю, я напишу очень хрупкие тесты.(Есть даже аргумент, что, если вы запутались с тестируемым объектом с помощью фальшивого фреймворка, вы даже больше не тестируете исходный объект, так что же вы тестируете?) Это внутренняя зависимость, которая вполне может измениться, не нарушая требований:
// ...
// refactored AccountMerger methods
// these still work, and still fulfil the two requirements above
public void Merge(Account first, Account second, MergeStrategy strategy)
{
MergeAndSave(first, second, strategy ?? MergeStrategy.Default);
}
public void Merge(Account first, Account second)
{
// note this no longer calls the other Merge() method
MergeAndSave(first, second, MergeStrategy.Default);
}
private void MergeAndSave(Account first, Account second, MergeStrategy strategy)
{
// merge logic goes here...
// [...]
dao.Save(first);
dao.Save(second);
}
// ...
Пока мои тесты проверяют только входные данные и эффекты, я легко могу выполнить такой рефакторинг - мои тесты будутдаже помогите мне сделать это, так как они удостоверяются, что я не нарушил класс при внесении изменений.
С другой стороны, я имею дело с AccountMerger
с использованием IAccountDao
для сохранения учетных записей послеслияние (хотя AccountMerger
не должно заботиться о реализации DAO, только то, что у него есть метод Save()
.) Этот DAO является главным кандидатом для насмешек - external зависимость AccountMerger
класс, чувствуя эффект Я хочу проверить входные данные .