Пересмешка - исключение вызова отсутствующего метода - PullRequest
0 голосов
/ 29 апреля 2018

У меня есть простая Java-программа, у которой есть класс обслуживания, который получает текущую цену BitCoin в евро - BitCoinValueService.java. Класс BitCoinPricer берет число из класса BitCoinValueService и конвертирует его в доллары.

Цель состоит в том, чтобы высмеять объект из класса BitCoinValueService, поскольку это число будет часто колебаться.

Вот код тестового класса:

@RunWith(JUnitParamsRunner.class)
public class BitcoinPricerTest {

    @Mock
    BitCoinValueService bsp; 

    @Before
    public void initMocks(){
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void testMock (){
        BitCoinPricer bp = new BitCoinPricer(bsp);
        Mockito.when(bsp.findPrice()).thenReturn(6000.00);

        assertEquals(bp.convertEuro(bsp.findPrice()),6000.00,1.0);
        Mockito.verify(bsp).findPrice();
    }
 }

Трассировка стека:

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 com.bitcoin.BitcoinPricerTest.testMock(BitcoinPricerTest.java:46)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
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:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at junitparams.JUnitParamsRunner.runChild(JUnitParamsRunner.java:416)
at junitparams.JUnitParamsRunner.runChild(JUnitParamsRunner.java:385)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

Код для класса BitCoinPricer

package com.bitcoin;

public class BitCoinPricer {

    static BitCoinValueService b = new BitCoinValueService();    

    public BitCoinPricer(BitCoinValueService b){
        this.b = b; 
    }

    public static  double convertEuro (double result){

        double euroVal = 1.227481; 

        result = b.findPrice() * euroVal;

        return result;

    }

}

Псевдокод для BitCoinValueService:

findprice(){
    double result; 
    // do this

    return double result; 
}

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

@DataProvider
public List<Object[]> dp(){
    final List<Object[]> result = new ArrayList<>();
    result.add( new Object[] {6000.00} );
    return result; 
}

@Test 
@UseDataProvider("dp")
public void testMock (double expectedVal) throws Exception{

    when(mockService.findPrice()).thenReturn(expectedVal);

    // Instantiate the object
    bcp = new BitCoinPricer (mockService);


    //Test begins 
    bcp.convertEuro(0);

    //checking condition
    assertEquals(bcp.convertEuro(expectedVal), 6000.00,0.1);

    verify(mockService, times(1)).findPrice();
}

Однако я получаю исключение для слишком многих аргументов.

Почему я продолжаю получать этот метод неправильного использования метода? Я устанавливаю цену, чтобы вернуться как 6000.00. Итак, я могу построить свои тесты Junit вокруг него. Любая помощь будет высоко ценится!

Ответы [ 2 ]

0 голосов
/ 30 апреля 2018

В вашем случае лучше просто создать макет в @BeforeClass с Mockito.mock(BitCoinValueService.class) и сбросить его на @After. Я предполагаю, что ваша насмешка была инициирована неправильно.

0 голосов
/ 29 апреля 2018

Если это не было опечаткой в ​​первоначальном вопросе, тестируемая система нуждается в рефакторинге.

public class BitCoinPricer {
    BitCoinValueService valueService;

    public BitCoinPricer(BitCoinValueService valueService){
        this.valueService = valueService; 
    }

    public double convertEuro (){
        double euroVal = 1.227481; 
        double result = valueService.findPrice() * euroVal;
        return result;
    }
}

Тест может выглядеть примерно так:

@RunWith(JUnitParamsRunner.class)
public class BitcoinPricerTest {
    @Before
    public void initMocks(){
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void testMock (){
        //Arrange
        double price = 6000.00;
        double expected = price * 1.227481;
        BitCoinValueService bsp = Mockito.mock(BitCoinValueService.class);
        Mockito.when(bsp.findPrice()).thenReturn(price);
        BitCoinPricer bp = new BitCoinPricer(bsp);

        //Act
        double actual = bp.convertEuro();

        //Assert
        assertEquals(expected, actual, 1.0);
        Mockito.verify(bsp).findPrice();
    }
}

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

...