У меня есть адаптер от I1
до ILogger
, реализованный так:
class BAdapter() implements I1
{
void logA() { // nothing }
void logB() { new BLogger().log() }
void logC() { // nothing }
}
Я хотел бы написать тест JUnit, который проверяет функциональность, но я нахожу это немного проблематичным, поскольку я не могу ввести свой объект Mock вместо BLogger
или проверить возвращаемое значение. Я нашел несколько возможных решений, но я не уверен, что является лучшим.
Случай один:
Добавьте void setLogger(Logger l)
к классу BAdapter
.
class BAdapter() implements I1
{
private Logger logger = new BLogger();
public void logB() { logger.log() }
public void setLogger(Logger l) { logger = l }
.. //rest of methods
}
Минусы: зачем добавлять сеттер, который никогда не используется в «реальном», не тестируемом коде?
Случай второй:
Добавьте защищенный заводской метод и подкласс BAdapter
в тестовом пакете.
class BAdapter() implements I1
{
public void logB() { createLogger().log() }
protected Logger createLogger() { retrun new BLogger() }
.. //rest of methods
}
class BAdapterForTesting extends BAdapter()
{
protected Logger createLogger() { retrun new MockBLogger() }
}
Минусы: я не уверен, если это чистое и элегантное решение, но я не вижу здесь много минусов.
Случай третий:
Используйте шаблон Abstract Factory.
class BAdapter() implements I1
{
public void logB() { AbstractFactory.getFactory().getBLogger().log() }
.. //rest of methods
}
И где-то в тестах:
AbstractFactory.setFactory(new MockLoggersFactory())
Минусы: это слишком сложно, не так ли?
Дело четвертое:
Возвратите логическое значение, например, при ведении журнала. Э.Г.
class BAdapter() implements I1
{
Boolean logA() { return false; }
Boolean logB() { return new BLogger().log() }
Boolean logC() { return false; }
}
Минусы: это своего рода обходной путь. Зачем возвращать какое-то значение, когда оно никому не нужно в «реальном», не тестируемом коде?
Лучшее решение?
Есть что-нибудь лучше?