Ответ 1
Не уверен, как с чистым EasyMock, но подумайте об использовании расширений PowerMock для EasyMock.
У этого есть много классных функций для того, чтобы делать только то, что вам нужно - https://github.com/jayway/powermock/wiki/MockStatic
Предположим, что у меня есть класс:
public class StaticDude{
public static Object getGroove() {
// ... some complex logic which returns an object
};
}
Как мне высмеять вызов статического метода, используя простой макет? StaticDude.getGroove()
.
Я использую простой mock 3.0
Не уверен, как с чистым EasyMock, но подумайте об использовании расширений PowerMock для EasyMock.
У этого есть много классных функций для того, чтобы делать только то, что вам нужно - https://github.com/jayway/powermock/wiki/MockStatic
Easymock - это платформа тестирования для "для интерфейсов (и объектов через расширение класса)", чтобы вы могли издеваться над классом без интерфейса. Подумайте о создании сопряженного объекта с помощью аксессуар для вашего статического класса, а затем издевайтесь над этим ассемблером.
EDIT: Btw, я бы не рекомендовал делать статические классы. Лучше иметь все сопряженное, если вы делаете TDD.
Только в случае PowerMock недоступен по любой причине:
Вы можете перенести статический вызов на метод, переопределить этот метод при создании тестируемого класса в тестовом классе, создать локальный интерфейс в тестовом классе и использовать его метод в методе overside:
private interface IMocker
{
boolean doSomething();
}
IMocker imocker = EasyMock.createMock(IMocker.class);
...
@Override
void doSomething()
{
imocker.doSomething();
}
...
EasyMock.expect(imocker.doSomething()).andReturn(true);
Вообще говоря, не представляется возможным издеваться над статическим методом, не используя какой-то аксессор, который, похоже, преследует цель использования статического метода. Это может быть довольно неприятно.
Есть один инструмент, который я знаю о названии "TypeMock Isolator", который использует какую-то сатанинскую магию, чтобы издеваться над статическими методами, но этот инструмент довольно дорог.
Проблема в том, что я не знаю, как переопределить статический метод. Вы не можете объявить его виртуальным. вы не можете включить его в интерфейс.
Извините, что отрицательный nelly.
Добавление примера о том, как реализовать статический макет по регулярному макету вводимых классов с помощью 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 Test с 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 Test с 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);
}
}