2012-05-09 5 views
4

Я хочу написать модульный тест для класса, который у меня есть. Этот класс имеет открытый метод, а внутри общедоступного метода есть вызовы для частных методов в одном классе. Я хочу издеваться над вызовами этих частных методов. Класс похож на это:Отказывание частных методов, используемых в общедоступном методе с PowerMock, Mockito и TestNG

public class SomeClass { 
    public int somePublicMethod(int num) { 
     int num2 = somePrivateMethod1(num); 
     int num3 = somePrivateMethod2(num); 

     return num2 + num3; 
    } 

    private int somePrivateMethod1(int num) { 
     return 2*num; 
    } 

    private int somePrivateMethod2(int num) { 
     return 3*num; 
    } 
} 

Для моего модульного тестирования Я пытаюсь использовать PowerMock с Mockito и TestNG. Вот моя попытка теста, который проверяет somePublicMethod:

import static org.powermock.api.mockito.PowerMockito.doReturn; 
import static org.powermock.api.mockito.PowerMockito.spy; 

import org.powermock.core.classloader.annotations.PrepareForTest; 
import org.testng.Assert; 
import org.testng.annotations.Test; 

@PrepareForTest(SomeClass.class) 
public class SomeClassTest { 

    @Test 
    public void testSomePublicMethod() throws Exception { 
     int num = 4;   

     SomeClass someClassSpy = spy(new SomeClass()); 

     doReturn(8).when(someClassSpy, "somePrivateMethod1", num); 
     doReturn(12).when(someClassSpy, "somePrivateMethod2", num); 

     int result = someClassSpy.somePublicMethod(num); 

     Assert.assertEquals(result, 20); 
    } 
} 

Когда я запускаю этот тест я получаю исключение и некоторые намеки:

FAILED: testSomePublicMethod 
org.mockito.exceptions.misusing.UnfinishedStubbingException: 
Unfinished stubbing detected here: 
-> at org.powermock.api.mockito.internal.PowerMockitoCore.doAnswer(PowerMockitoCore.java:31) 

E.g. thenReturn() may be missing. 
Examples of correct stubbing: 
    when(mock.isOk()).thenReturn(true); 
    when(mock.isOk()).thenThrow(exception); 
    doThrow(exception).when(mock).someVoidMethod(); 
Hints: 
1. missing thenReturn() 
2. you are trying to stub a final method, you naughty developer! 

Я посмотрел на некоторых примерах в Интернете, но я гавань» t нашел тот, который использует PowerMock с Mockito и TestNG специально для того, чтобы делать то, что я хочу. Может ли кто-нибудь дать мне несколько указаний на то, что я мог бы сделать по-другому?

ответ

0

Я думаю, что вы нажимаете предел Mockito здесь. В подобных случаях я использую замену метода Powermock или объявляю целевой метод как защищенный и переопределяю его при построении тестируемого экземпляра класса. Надеюсь, что помогает.

1

Вы не можете сделать это. Вы пытались использовать отражение?

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

Надеюсь, что эта помощь.

5

Я не думаю, что это проблема с PowerMock. Похоже, он должен работать нормально, как есть. Интересно, существует ли проблема с TestNG, взаимодействующим с PowerMock?

У меня нет опыта работы с TestNG, поэтому я попробовал запустить класс в JUnit. SomeClass была оставлена ​​как есть, SomeClassTest был минимально изменен, чтобы использовать JUnit:

import static org.powermock.api.mockito.PowerMockito.*; 

import org.junit.Assert; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.powermock.core.classloader.annotations.PrepareForTest; 
import org.powermock.modules.junit4.PowerMockRunner; 

@RunWith(PowerMockRunner.class) 
@PrepareForTest(SomeClass.class) 
public class SomeClassTest { 

    @Test 
    public void testSomePublicMethod() throws Exception { 
     final int num = 4; 

     final SomeClass someClassSpy = spy(new SomeClass()); 

     doReturn(8).when(someClassSpy, "somePrivateMethod1", num); 
     doReturn(12).when(someClassSpy, "somePrivateMethod2", num); 

     final int result = someClassSpy.somePublicMethod(num); 

     Assert.assertEquals(result, 20); 
    } 
} 

Испытание проходит.

Нужно указать PowerMockRunner.class, используя @RunWIth или аналогичную аннотацию, как в JUnit? Если я удалю эту аннотацию, я получаю то же сообщение об ошибке, которое вы отправили.

EDIT:

По этой ссылке: http://code.google.com/p/powermock/wiki/TestNG_usage

Вы должны сказать TestNG использовать объект PowerMock завод. Чтобы сделать это программно добавить метод, как это ваш тестовый класс:

@ObjectFactory 
public IObjectFactory getObjectFactory() { 
    return new org.powermock.modules.testng.PowerMockObjectFactory(); 
} 

или быть на безопасной стороне вы также можете проходить от PowerMockTestCase:

@PrepareForTest(SomeClass.class) 
public class SomeClassTest extends PowerMockTestCase { 
    //... 
} 
Смежные вопросы