Вызовите вызов super.method (), используя mockito [duplicate]

Как уже упоминалось в парах других, нет способа стилизовать родительский элемент элемента, используя только CSS, но следующее работает с jQuery :

$("a.active").parents('li').css("property", "value");

70
задан Evan Kroske 8 November 2016 в 01:10
поделиться

7 ответов

Нет, Mockito этого не поддерживает.

Возможно, это не тот ответ, который вы ищете, но то, что вы видите, является симптомом отказа от применения принципа дизайна:

Использовать композицию над наследованием

Если вы извлечете стратегию вместо расширения суперкласса, проблема исчезнет.

] Если вам не разрешено изменять код, но вы все равно должны его протестировать, и в этом неудобном случае все еще есть надежда. С некоторыми инструментами AOP (например, AspectJ) вы можете переплетать код в метод суперкласса и полностью исключить его выполнение (yuck). Это не работает, если вы используете прокси-серверы, вы должны использовать модификацию байтового кода (время ткачества или компиляцию времени). Есть и фальшивые фреймворки, которые поддерживают этот тип трюков, например PowerMock и PowerMockito.

Я предлагаю вам пойти на рефакторинг, но если это не вариант, вы можете провести какое-то серьезное взлом .

51
ответ дан iwein 18 August 2018 в 18:50
поделиться
  • 1
    Я не вижу нарушения LSP. У меня примерно такая же настройка, как и у OP: базовый класс DAO с методом findAll () и подкласс DAO, который переопределяет базовый метод, вызывая super.findAll (), а затем сортируя результат. Подкласс заменяется на все контексты, принимающие суперкласс. Неужели я не понимаю ваш смысл? – Willie Wheeler 8 July 2011 в 22:55
  • 2
    Я удалю примечание LSP (это не добавит значения для ответа). – iwein 2 August 2011 в 09:40
  • 3
    Да, наследование сосет, и тупой каркас, за которым я застрял, сконструирован с наследованием как единственный вариант. – Sridhar-Sarnobat 21 December 2015 в 23:07
  • 4
    Предполагая, что вы не можете перепроектировать суперкласс, вы можете извлечь код //some codes в метод, который может быть протестирован отдельно. – Phasmal 17 February 2016 в 17:38
  • 5
    Хорошо понял. Это другая проблема, чем то, что я пытался решить, когда я искал это, но по крайней мере это недоразумение решило мою проблему, чтобы издеваться над вызовом из базового класса (что я не переопределяю). – Guillaume Perrot 9 February 2017 в 18:22

Даже если я полностью согласен с ответом iwein (

предпочитает композицию над наследованием

), я допускаю, что наследование наследования несколько раз кажется естественным, и я не чувствую взлома или рефакторирования его только для модульного теста.

Итак, мое предложение:

/**
 * BaseService is now an asbtract class encapsulating 
 * some common logic callable by child implementations
 */
abstract class BaseService {  
    protected void commonSave() {
        // Put your common work here
    }

    abstract void save();
}

public ChildService extends BaseService {  
    public void save() {
        // Put your child specific work here
        // ...

        this.commonSave();
    }  
}

И затем в модульном тесте:

    ChildService childSrv = Mockito.mock(ChildService.class, Mockito.CALLS_REAL_METHODS);

    Mockito.doAnswer(new Answer<Void>() {
        @Override
        public Boolean answer(InvocationOnMock invocation)
                throws Throwable {
            // Put your mocked behavior of BaseService.commonSave() here
            return null;
        }
    }).when(childSrv).commonSave();

    childSrv.save();

    Mockito.verify(childSrv, Mockito.times(1)).commonSave();

    // Put any other assertions to check child specific work is done
0
ответ дан dams50 18 August 2018 в 18:50
поделиться

создать защищенный пакет (предполагается, что класс теста в том же пакете) в подклассе, который вызывает метод суперкласса, а затем вызывать этот метод в методе переопределенного подкласса. вы можете установить ожидания этого метода в своем тесте с помощью шаблона шпиона. не очень, но, конечно, лучше, чем иметь дело со всеми настройками ожидания для супер метода в вашем тесте

1
ответ дан Luke 18 August 2018 в 18:50
поделиться
  • 1
    могу ли я также сказать, что состав над наследованием почти всегда лучше, но иногда его просто проще использовать наследование. пока java не включит лучшую композиционную модель, такую ​​как scala или groovy, это всегда будет иметь место, и эта проблема будет продолжать существовать – Luke 22 May 2012 в 23:07

Рассмотрим рефакторинг кода из метода ChildService.save () для другого метода и протестируйте этот новый метод вместо тестирования ChildService.save (), таким образом вы избежите ненужного вызова метода super.

Пример :

class BaseService {  
    public void save() {...}  
}

public Childservice extends BaseService {  
    public void save(){  
        newMethod();    
        super.save();
    }
    public void newMethod(){
       //some codes
    }
} 
4
ответ дан Mohammed Misbahuddin 18 August 2018 в 18:50
поделиться

Если у вас действительно нет выбора для рефакторинга, вы можете высмеивать / заглушить все в вызове супер метода, например

    class BaseService {

        public void validate(){
            fail(" I must not be called");
        }

        public void save(){
            //Save method of super will still be called.
            validate();
        }
    }

    class ChildService extends BaseService{

        public void load(){}

        public void save(){
            super.save();
            load();
        }
    }

    @Test
    public void testSave() {
        ChildService spy = Mockito.spy(new ChildService());

        // Prevent/stub logic in super.save()
        Mockito.doNothing().when((BaseService)spy).validate();

        // When
        spy.save();

        // Then
        verify(spy).load();
    }
67
ответ дан Mohd Farid 18 August 2018 в 18:50
поделиться
  • 1
    этот код фактически не будет препятствовать вызову super.save (), поэтому, если вы много делаете в super.save (), вам нужно будет предотвратить все эти вызовы ... – iwein 2 August 2011 в 09:47
  • 2
    фантастическое решение творит чудеса для меня, когда я хочу вернуть издеваемое значение из метода суперкласса для использования ребенком, фантастическое спасибо. – Gurnard 31 May 2012 в 15:18
  • 3
    Большое спасибо. – Saeed Zarinfam 28 January 2013 в 11:42
  • 4
    это работает хорошо, если проверка не скрыта, или метод сохранения выполняет работу напрямую, а не вызывает другой метод. mockito не делает: Mockito.doNothing (). когда ((BaseService) шпион) .save (); это не будет «doNothing» на базовом сервисе save, а на childService save :( – tibi 15 August 2013 в 13:47
  • 5
    @ Sridhar-Sarnobat, да, я вижу одно и то же: (кто-нибудь знает, как заставить его только опустить super.validate()? – stantonk 13 January 2016 в 01:00

Возможно, самый простой вариант, если наследование имеет смысл, - создать новый метод (private private), чтобы вызвать супер (позволяет называть его superFindall), заглянуть в реальный экземпляр и затем высмеять метод superFindAll () таким образом, как вы хотел высмеять родительский класс. Это не идеальное решение с точки зрения охвата и видимости, но оно должно выполнять эту работу, и ее легко применять.

 public Childservice extends BaseService {
    public void save(){
        //some code
        superSave();
    }

    void superSave(){
        super.save();
    }
}
0
ответ дан Rubasace 18 August 2018 в 18:50
поделиться

Причина в том, что ваш базовый класс не является общедоступным, тогда Mockito не может перехватить его из-за видимости, если вы измените базовый класс как общедоступный или @Override в подклассе (как общедоступный), то Mockito может издеваться над ним правильно.

public class BaseService{
  public boolean foo(){
    return true;
  }
}

public ChildService extends BaseService{
}

@Test
@Mock ChildService childService;
public void testSave() {
  Mockito.when(childService.foo()).thenReturn(false);

  // When
  assertFalse(childService.foo());
}
0
ответ дан zoufeiyy 18 August 2018 в 18:50
поделиться
  • 1
    Дело не в этом. ChildService должен переопределить foo (), и проблема заключается в том, как издеваться над BaseService.foo (), но не с ChildService.foo () – Adriaan Koster 30 September 2015 в 12:43
Другие вопросы по тегам:

Похожие вопросы: