Как мне макетировать статические методы в классе с помощью easymock? - PullRequest
29 голосов
/ 02 июля 2010

Предположим, у меня есть такой класс:

public class StaticDude{
    public static Object getGroove() {
        // ... some complex logic which returns an object
    };
}

Как мне смоделировать статический вызов метода с помощью easy mock? StaticDude.getGroove().

Я использую легкий макет 3.0

Ответы [ 5 ]

25 голосов
/ 02 июля 2010

Не знаю, как с чистым EasyMock, но подумайте об использовании PowerMock расширений для EasyMock.

В нем много интересных функций для выполнения именно того, что вам нужно - https://github.com/jayway/powermock/wiki/MockStatic

11 голосов
/ 02 июля 2010

Easymock - это среда тестирования «для интерфейсов (и объектов через расширение класса)», поэтому вы можете смоделировать класс без интерфейса. Подумайте о создании интерфейсного объекта с аксессором для вашего статического класса, а затем смоделируйте его вместо этого.

РЕДАКТИРОВАТЬ: Кстати, я бы не рекомендовал делать статические классы. Лучше, чтобы все было сопряжено, если вы делаете TDD.

9 голосов
/ 30 августа 2012

На всякий случай PowerMock недоступен по любой причине:

Вы можете переместить статический вызов метода, переопределить этот метод при создании экземпляра тестируемого класса в тестовом классе, создать локальный интерфейс в тестовом классе и использовать его метод в методе overidden:

private interface IMocker 
{
    boolean doSomething();
}

IMocker imocker = EasyMock.createMock(IMocker.class);

...

@Override
void doSomething()
{
     imocker.doSomething();
}

...

EasyMock.expect(imocker.doSomething()).andReturn(true);
4 голосов
/ 07 июля 2010

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

Существует один инструмент, который я знаю, называемый "TypeMock Isolator", который использует какую-то сатанинскую магию для насмешки статических методов, но этот инструмент довольно дорогой.Проблема в том, что я не знаю способа переопределить статический метод.Вы не можете объявить это виртуальным.Вы не можете включить его в интерфейс.

Извините, что я отрицательный.

1 голос
/ 16 февраля 2017

Добавление примера о том, как реализовать статический макет вдоль регулярного макета внедренных классов с помощью EasyMock / PowerMock, поскольку связанный пример показывает только статический макет.

А с PowerMockRunner службы @Mock не подключены к службе @TestSubject для тестирования.

Допустим, у нас есть сервис, который мы хотим протестировать, ServiceOne:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class ServiceOne {

    @Autowired
    private ServiceTwo serviceTwo;

    public String methodToTest() {
        String returnServ2 = serviceTwo.methodToMock();
        return ServiceUtils.addPlus(returnServ2);
    }
}

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

import org.springframework.stereotype.Service;

@Service
public class ServiceTwo {

    public String methodToMock() {
        return "ServiceTwoReturn";
    }
}

И который вызывает статический метод конечного класса, ServiceUtils:

public final class ServiceUtils {

    public static String addPlus(String pParam) {
        return "+" + pParam;
    }
}

При звонке ServiceOne.methodToTest() мы получаем "+ServiceTwoReturn" в качестве возврата.


Тест Junit с EasyMock, дразня только внедренный сервис ServiceTwo Spring:

import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.junit.Assert.assertEquals;

import org.easymock.EasyMockRunner;
import org.easymock.Mock;
import org.easymock.TestSubject;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(EasyMockRunner.class)
public class ExempleTest {

    @TestSubject
    private ServiceOne serviceToTest = new ServiceOne();

    @Mock
    private ServiceTwo serviceMocked;

    @Test
    public void testMethodToTest() {
        String mockedReturn = "return2";

        expect(serviceMocked.methodToMock()).andReturn(mockedReturn);
        replay(serviceMocked);

        String result = serviceToTest.methodToTest();

        verify(serviceMocked);

        assertEquals("+" + mockedReturn, result);
    }
}

Тест Junit с EasyMock & PowerMock, высмеивающий внедренный сервис ServiceTwo Spring, а также последний класс и его статический метод:

import static org.easymock.EasyMock.expect;
import static org.junit.Assert.assertEquals;
import static org.powermock.api.easymock.PowerMock.createMock;
import static org.powermock.api.easymock.PowerMock.mockStatic;
import static org.powermock.reflect.Whitebox.setInternalState;

import org.easymock.Mock;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest(ServiceUtils.class)
public class ExempleTest {

    private ServiceOne serviceToTest;

    private ServiceTwo serviceMocked;

    @Before
    public void setUp() {
        serviceToTest = new ServiceOne();
        serviceMocked = createMock(ServiceTwo.class);
        // This will wire the serviced mocked into the service to test
        setInternalState(serviceToTest, serviceMocked);
        mockStatic(ServiceUtils.class);
    }

    @Test
    public void testMethodToTest() {
        String mockedReturn = "return2";
        String mockedStaticReturn = "returnStatic";

        expect(serviceMocked.methodToMock()).andReturn(mockedReturn);
        expect(ServiceUtils.addPlus(mockedReturn)).andReturn(mockedStaticReturn);
        PowerMock.replayAll();

        String result = serviceToTest.methodToTest();

        PowerMock.verifyAll();

        assertEquals(mockedStaticReturn, result);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...