Кстати, даже в этом коде есть логика, которую можно тестировать
Либо ты должен проверять параметры конструктора и кидать исключение в случае если logger или calculator имеют нулевые значения. Либо ты должен проверять на ноль непосредственно при сложении. Т.е. тут цикломатическая сложность гарантированно больше 1, а значит надо делать тест. Можно конечно назвать этот тест интеграционным, но мне кажется, что это уже дрочерство на терминологию
Так я выше написал, что этот класс будет тестироваться с помощью интеграционных тестов. Ну добавь туда проверку на null, если тебе так нужно, я же пример привел, а не конечное приложение.
Да, вот только функция уровнем выше (которая будет использовать CalculatorWithLogger) ничего не должна знать про существование CalculatorWithLogger, ей известен только ICalculator... Т.е. либо тебе придется вводить еще одну абстракцию, либо ты рискуешь совершить ошибку передав в CalculatorWithLogger в качестве ICalculator другой CalculatorWithLogger.
Если у тебя будет как ты выше написал CalculatorWithLogger, CalculatorWithDatabase, CalculatorWithLoggarAndDatabase, то тут в любом случае придется вводить интерфейс. Ты уже докапываешься до незначительных деталей ИМХО.
Проблема в том, что эта функция должна либо сама создать объект CalculatorWithLogger (для этого ей надо будет как-то получить ILogger и ICalculator), либо функция должна будет получить CalculatorWithLogger в качестве параметра (это насколько я понимаю, противоречит требованию к юнит-тесту)
Какая эта функция? Я тебя не понимаю. Обработчик ГУИ формы? CalculatorWithLogger - это внешнее API, которые ты юзаешь в своем коде, а Calculator - это внутреняя бизнес логика, которая тестируется с помощью ЮТ.