2017-01-20 2 views
3

Я использую следующий метод для проверки обновления объекта Profile в моем проекте. .Тест-драйв JUnit/Mockito передается в режиме отладки, но не в режиме запуска

import org.apache.commons.collections.MapUtils; 
import org.junit.Assert; 
import org.junit.Before; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.mockito.InjectMocks; 
import org.mockito.Mock; 
import org.mockito.Mockito; 
import org.mockito.invocation.InvocationOnMock; 
import org.mockito.runners.MockitoJUnitRunner; 
import org.mockito.stubbing.Answer; 
import org.powermock.api.mockito.PowerMockito; 
import org.powermock.core.classloader.annotations.PrepareForTest; 

import java.math.BigInteger; 
import java.util.*; 
import java.util.concurrent.Callable; 


@RunWith(MockitoJUnitRunner.class) 
@PrepareForTest({TxUtils.class}) 
public class MonitoringProfileServicesImplTest extends MonitoringProfileServicesImpl { 

    private MutableDataObject mutableDataObject = Mockito.mock(MutableDataObject.class); 

    @Mock 
    private PersistenceContext<MutableDataObject> persistenceContext; 

    @Mock 
    PersistenceContextHelper persistenceContextHelper; 

    @Mock 
    MonitoringDao monitoringDao; 

    @InjectMocks 
    private MonitoringProfileServicesImpl service; 

    private BigInteger profileId; 

    private Map<String, BigInteger> attributeNameIdMap; 

    private Map<BigInteger, String> invAttributeNameIdMap; 

    ResponseBean responseBean = new ResponseBean(); 


    @Before 
    public void setUp() { 
     Mockito.when(persistenceContextHelper.getLocalPersistenceContext()).thenReturn(persistenceContext); 

     profileId = BigInteger.valueOf(Long.valueOf(1L)); 

     attributeNameIdMap = new HashMap<String, BigInteger>(); 
     invAttributeNameIdMap = new HashMap<BigInteger, String>(); 
     attributeNameIdMap.put("key", BigInteger.valueOf(1111L)); 
     invAttributeNameIdMap = MapUtils.invertMap(attributeNameIdMap); 
    } 


@Test 

public void testXXXX() { 
     MonitoringProfile monitoringProfile = getDummyMonitoringProfileToBeCreated(); 

    TransactionServicePALImpl transactionImpl = Mockito.mock(TransactionServicePALImpl.class); 
    Mockito.when(transactionImpl.getTM()).thenReturn(new TransactionManagerImplTest()); 


    Mockito.when(mutableDataObject.getId()).thenReturn(BigInteger.valueOf(1000)); 
    Mockito.when(mutableDataObject.getName()).thenReturn("Name"); 

    Mockito.when(persistenceContext.getObjectById(Mockito.any(BigInteger.class))).thenReturn(mutableDataObject); 
    Mockito.when(monitoringDao.getAttributeIdsForObjectType(Mockito.any(BigInteger.class))).thenReturn(invAttributeNameIdMap); 

    TxUtils mock = PowerMockito.mock(TxUtils.class); 
    System.out.println("newresponseBean:::"); 



     PowerMockito.when(mock.doTxRequired(new Callable<Object>() { 
      @Override 
      public Object call() throws Exception { 

       return this; 
      } 

     })).thenAnswer(new Answer<ResponseBean>() { 
      @Override 
      public ResponseBean answer(InvocationOnMock invocation) throws Throwable { 

       responseBean.setResultObj(monitoringProfile); 
       return responseBean; 
      } 
     }); 


    ResponseBean newresponseBean = service.updateMonitoringProfile(monitoringProfile, BigInteger.valueOf(1000)); 
    Assert.assertNotNull(newresponseBean); 
    Assert.assertNotNull(newresponseBean.getResultObj()); 
    Assert.assertNull(newresponseBean.getErrorObj()); 
} 

    } 

** В рабочем режиме он становится потерпело неудачу на следующую строку

PowerMockito.when(mock.doTxRequired(new Callable<Object>()..... 

В то время как в режиме отладки он работает отлично **

Ниже метод обслуживания кода;

public ResponseBean updateMonitoringProfile(@RequestBody MonitoringProfile profileToUpdate) {   
     ResponseBean responseBean = TxUtils.doTxRequired(() -> { 
      ResponseBean response = new ResponseBean(); 
      try { 
       PersistenceContext<MutableDataObject> localPersistenceContext = persistenceContextHelper.getLocalPersistenceContext(); 
       MutableDataObject monitoringProfile = localPersistenceContext.getObjectById(profileToUpdate.getId()); 
       ParamsBuilder paramsBuilder = populateProfileParameterValues(profileToUpdate, monitoringProfile).build(); 
       localPersistenceContext.flush(); 
       response.setResultObj(profileToUpdate); 
      } catch (NotUpdatedException notUpdatedEx) { 
       notUpdatedEx.printStackTrace(); 
      } 
      return response; 
     }); 
     return responseBean; 
    } 

Следующее исключение мы получаем во время работы в режиме Run;

newresponseBean::: 

org.mockito.exceptions.misusing.MissingMethodInvocationException: 
when() requires an argument which has to be 'a method call on a mock'. 
For example: 
    when(mock.getArticles()).thenReturn(articles); 

Also, this error might show up because: 
1. you stub either of: final/private/equals()/hashCode() methods. 
    Those methods cannot be stubbed/verified. 
    Mocking methods declared on non-public parent classes is not supported. 
2. inside when() you don't call method on mock but on some other object. 


at org.powermock.api.mockito.PowerMockito.when(PowerMockito.java:495) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
at java.lang.reflect.Method.invoke(Method.java:483) 
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) 
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) 
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) 
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) 
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) 
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) 
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) 
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) 
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) 
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) 
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) 
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) 
at org.junit.runners.ParentRunner.run(ParentRunner.java:363) 
at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37) 
at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62) 
at org.junit.runner.JUnitCore.run(JUnitCore.java:137) 
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) 
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51) 
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237) 
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
at java.lang.reflect.Method.invoke(Method.java:483) 
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147) 


Process finished with exit code -1 
+1

Добро пожаловать в StackOverflow. Пожалуйста, посмотрите [раздел справки о запросе] (http://stackoverflow.com/help/asking). Когда я смотрю на вопрос, у меня создается впечатление, что это тип «Почему это не работает?». Рассмотрите возможность предоставления [минимального полного и проверяемого примера] (http://stackoverflow.com/help/mcve), иначе вопрос может быть вскоре закрыт. – hotzst

+0

Обновить данные в вопросе. –

+0

Зачем вам нужно формовать макет внутри блока 'synchronized'? Все действия должны быть предварительно сформированы перед действием. Нет необходимости синхронизироваться! –

ответ

1

Если наблюдение действительно так, и вы не столкнетесь с этой проблемой, когда пошагового теста в режиме «отладки»; но он устойчив при нормальной работе теста, то это должно быть какая-то проблема времени.

Я думаю, что у вас есть Синхронизированный оператор в вашем тестовом коде - это указание, что какой-то код, который вы здесь не показываете, будет использовать несколько потоков ?!

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

Помимо этого: вы получаете часть «издевательская спецификация» неправильный. Вы хотите проинструктировать свою среду, что , когда статический метод mock.doTxRequired() вызывается с аргументом, то то или это должно произойти.

Другими словами: нет смысла предоставлять новый объект, созданный в вашем предложении when(). Напротив: насмешливая структура проверяет во время выполнения, если аргумент, переданный во время выполнения, равен , равному объекту, указанному в вашем предложении if()! И поскольку вы не используете равных в своем анонимном внутреннем классе ... PowerMock будет never определить, что макет был вызван с этим объектом.

Другими словами: вы, вероятно, захотите использовать какой-либо объект, который будет равен тому, что будет передано во время выполнения; или вы используете сопоставление аргументов как «any()» или так (см. here).

И только для записи: если у вас есть возможность рассмотреть возможность не использования вызовов статического метода и избежать с помощью PowerMock.

+0

** Спасибо @GhostCat! Цените свои отзывы. Даже мы попытались удалить синхронизированный блок, он дает ту же самую проблему, i.e работает в режиме отладки и не работает в режиме запуска. Даже мы пытались со следующими;. ** \t \t 'PowerMockito.when (mock.doTxRequired (Mockito.anyObject())) thenAnswer (новый ответ () {...
\t \t Это не работает и бросает NullPointerException' –

+0

Пожалуйста, обновите свой вопрос соответствующим образом. Но тогда: действительно посмотрите на предложение [mcve]. Ваш код ** слишком сложный, чтобы помочь. Я предлагаю: вы заходите и шаг: уменьшите это. Или наоборот: напишите ** новый ** тестовый файл, который ничего не делает ** ничего, кроме того, что он издевается над этим статическим вызовом. И когда это работает, вы медленно добавляете все, что у вас есть в вашем Это единственный совет, который у меня есть. – GhostCat

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