簡體   English   中英

JUnit / Mockito測試用例在調試模式下傳遞,但不在運行模式下傳遞

[英]JUnit/Mockito Test case gets passed in Debug Mode but not in Run mode

我正在使用以下方法來測試項目中的配置文件對象更新。

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;
    }

我們在運行模式下運行時遇到異常;

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

如果您的觀察結果是真實的,並且在“調試”模式下單步執行測試用例時不會遇到此問題; 但是在正常運行測試時它是穩固的,那么它必然是某種時序問題。

我想在你的測試代碼中你有同步語句這一點表明你在這里沒有顯示的某些代碼將使用多個線程?!

因此,鑒於我們無法瑞普這個問題; 這是我建議你研究的部分。

除此之外:你得到的“模擬規范”部分是錯誤的 您想要告訴您的環境, 使用某個參數調用靜態方法mock.doTxRequired()時,應該發生這種情況。

換句話說:在when()子句中提供創建的對象沒有意義。 相反:如果在運行時傳遞的參數等於您在when()子句中指定的對象,則模擬框架將在運行時檢查! 因為你沒有在你的匿名內部類中實現equals ... PowerMock 永遠不會確定使用該Object調用了mock。

換句話說:你可能想要使用一些等於將在運行時傳遞的對象; 或者你使用像“any()”這樣的參數匹配器(詳見這里 )。

只是為了記錄:如果你有可能考慮使用靜態方法調用並避免使用PowerMock。

我有同樣的問題。 它在運行測試時隨機失敗,但在調試時總是通過。

問題是我的測試類是從基礎測試類繼承的,我在這兩個類中都模擬了相同的服務。 刪除子類中的模擬后,一切都修復了

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM