2015-08-18 2 views
5

Как использовать Mockito или PowerMock для подделки защищенного метода, который реализуется подклассом, но унаследован от абстрактного суперкласса?Как обмануть защищенный метод подкласса, унаследованный от абстрактного класса?

Другими словами, я хочу протестировать метод «doSomething», высмеивая «doSomethingElse».

Аннотация супер класс

public abstract class TypeA { 

    public void doSomething() {  

     // Calls for subclass behavior 
     doSomethingElse();  
    } 

    protected abstract String doSomethingElse(); 

} 

реализации Подкласс

public class TypeB extends TypeA { 

    @Override 
    protected String doSomethingElse() { 
     return "this method needs to be mocked"; 
    } 

} 

Решение

Ответы, приведенные здесь, являются правильными d будет работать, если участвующие классы находятся в одном пакете.

Но если разные пакеты задействованы один вариант для пользователя PowerMock. Следующий пример работал на меня. Конечно, могут быть другие способы сделать это, это тот, который работает.

import static org.junit.Assert.assertEquals; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.powermock.api.mockito.PowerMockito; 
import org.powermock.core.classloader.annotations.PrepareForTest; 
import org.powermock.modules.junit4.PowerMockRunner; 

@RunWith(PowerMockRunner.class) 
@PrepareForTest({ TypeB.class }) 
public class TestAbstract { 

    @Test 
    public void test_UsingPowerMock() throws Exception { 
     // Spy a subclass using PowerMock 
     TypeB b = PowerMockito.spy(new TypeB()); 
     String expected = "some value for mock"; 

     // Mock a method by its name using PowerMock again 
     PowerMockito.doReturn(expected).when(b, "doSomethingElse"); 

     // Calls the 
     String actual = b.doSomething(); 
     assertEquals(expected, actual);  

    } 
} 

Примечание: Испытания, проведенные с использованием Java 5, JUnit 4.11 Mockito 1.9.0 и PowerMock 1.4.12.

+1

Этот подход дает мне «NullPointerException» с Java 8, JUnit 4.12 и PowerMock 1.6.4. – Mack

ответ

5

Вы можете использовать Mockito.CALLS_REAL_METHODS когда насмешливый абстрактный метод. Это вызовет оригинальные методы класса, и вы можете самостоятельно издеваться над всеми абстрактными методами.

TypeA typeA = mock(TypeA.class, Mockito.CALLS_REAL_METHODS); 
when(typeA.doSomethingElse()).thenReturn("Hello"); 
typeA.doSomething(); 

Или проверить непосредственно на TypeB с шпиона:

TypeB typeB = spy(new TypeB()); 
when(typeB.doSomethingElse()).thenReturn("Hello"); 
typeB.doSomething(); 
+1

1-й вариант не работает, потому что TypeA является абстрактным. Вариант 2 работает с 'spy()', но когда я пытаюсь применить его к моему производственному коду, он дает мне «Метод из типа <имя подкласса> не отображается». Попытка выяснить, почему. – BonanzaOne

+0

На самом деле ваш тест правильный, но у меня есть классы, которые находятся в разных пакетах, поэтому я не смог сделать это раньше. Методы не видны из других упаковок при их защите. – BonanzaOne

+0

Был ли первый вариант работы?Я тестировал как с Mockito 1.10.19, так и с последней бета-версией, и обе работают, как ожидалось. – mszalbach

3

Вы можете проверить свой класс Abtract используя Mockito следующим образом

TypeA typA = Mockito.mock(TypeA.class, Mockito.CALLS_REAL_METHODS); 
when(typA.doSomethingElse()).thenReturn("doSomethingElse"); 
Assert.assertSomething(typeA.doSomething()); 
4

Я предлагаю использовать Mockito для этого:

// Create a new Mock 
final TypeA a = Mockito.mock(TypeA.class, Mockito.CALLS_REAL_METHODS); 

// Call the method 
a.doSomething(); 

// Now verify that our mocked class' method was called 
Mockito.verify(a, Mockito.times(1)).doSomethingElse(); 
+0

Это работает, но я просто понял, что у меня есть классы в разных пакетах в моем производственном коде. Тогда защищенные методы не видны. – BonanzaOne

+0

Это создает проблему. Возможным решением было бы использовать PowerMock, который должен иметь возможность проверять частные методы, afaik. Тем не менее, он никогда не использовал его. –

2

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

MyAbstractClass abs = Mockito.mock(MyAbstractClass.class); 
Mockito.doNothing().when(abs).myMethod(arg1,arg2....)); 

Мы можем заменить аргументы Mockito.anyString() и т. Д. В соответствии с требованиями.

Смежные вопросы