2013-08-13 6 views
0

Я использую PowerMock простой макет для издевательства статического метода класса. У меня есть два тестовых примера, написанных, которые, если я запускаю независимо, работают нормально, но дайте мне ошибку при одновременном запуске.Ошибка мошенничества с ошибкой Powermock с использованием пружины при издевательском статическом объекте

CarTest:

@RunWith(PowerMockRunner.class) 
@PrepareForTest({ ServiceCaller.class }) 
public class CarTest { 

    ServiceCaller   mockServiceCallerObjectToReturn; 

    public CarTest() { 
    PowerMock.mockStaticPartial(ServiceCaller.class, "getInstance"); 
    mockServiceCallerObjectToReturn = PowerMock.createMock(ServiceCaller.class); 
    EasyMock.expect(ServiceCaller.getInstance()).andReturn(mockServiceCallerObjectToReturn); 
    } 

    @Test 
    public void test1() throws IOException { 
    PowerMock.reset(mockServiceCallerObjectToReturn); 
    PowerMock.reset(ServiceCaller.class); 

    EasyMock.expect(ServiceCaller.getInstance()).andReturn(mockServiceCallerObjectToReturn); 

    EasyMock.expect(mockServiceCallerObjectToReturn.checkValidity("testDriver")).andReturn(false); 

    PowerMock.replay(mockServiceCallerObjectToReturn); 
    PowerMock.replay(ServiceCaller.class); 

    Car car = CarFactory.getInstance().getCar(); 
    boolean canDrive = car.drive("testDriver"); 
    Assert.assertEquals(canDrive, false); 

    PowerMock.verify(mockServiceCallerObjectToReturn); 
    PowerMock.verify(ServiceCaller.class); 
    } 

    @Test 
    public void test2() throws IOException { 
    PowerMock.reset(mockServiceCallerObjectToReturn); 
    PowerMock.reset(ServiceCaller.class); 

    EasyMock.expect(ServiceCaller.getInstance()).andReturn(mockServiceCallerObjectToReturn); 

    EasyMock.expect(mockServiceCallerObjectToReturn.checkValidity("testDriver")).andReturn(false); 

    PowerMock.replay(mockServiceCallerObjectToReturn); 
    PowerMock.replay(ServiceCaller.class); 

    Car car = CarFactory.getInstance().getCar(); 
    boolean canDrive = car.drive("testDriver"); 
    Assert.assertEquals(canDrive, false); 

    PowerMock.verify(mockServiceCallerObjectToReturn); 
    PowerMock.verify(ServiceCaller.class); 
    } 
} 

CarFactory:

public class CarFactory {  
    private static final String    CAR_SPRING_CONTEXT_XML = "/com/archit/mock/spring-config/CarSpringContext.xml";  
    protected static final ApplicationContext CONTEXT    = new ClassPathXmlApplicationContext(new String[] { CAR_SPRING_CONTEXT_XML });  
    private static final CarFactory   INSTANCE    = new CarFactory();  
    public static CarFactory getInstance() { 
    return INSTANCE; 
    }  
    public Car getCar() { 
    return CONTEXT.getBean("car", Car.class); 
    }  
} 

Автомобиль:

package com.archit.mock; 
public class Car { 
    private final ServiceCaller  serviceCaller; 
    public Car(final ServiceCallerFactory serviceCallerFactory) { 
    this.serviceCaller = serviceCallerFactory.getServiceCaller(); 
    } 
    public boolean drive(final String driver) { 
    return (serviceCaller.checkValidity(driver)); 
    } 
} 

ServiceCaller:

package com.archit.mock; 
public class ServiceCaller { 
    private static class ServiceCallerHolder { 
    private static ServiceCaller INSTANCE = new ServiceCaller(); 
    } 
    public static ServiceCaller getInstance() { 
    return ServiceCallerHolder.INSTANCE; 
    } 
    public boolean checkValidity(final String x) { 
    // Do some call 
    throw new IllegalStateException("This should have been mocked"); 
    } 
} 

ServiceCallerFactory:

package com.archit.mock; 
public class ServiceCallerFactory { 
    public ServiceCaller getServiceCaller() { 
    return ServiceCaller.getInstance(); 
    } 
} 

Spring Config:

<bean name="car" class="com.archit.mock.Car"> 
    <constructor-arg> 
     <ref bean="serviceCallerFactory" /> 
    </constructor-arg> 
</bean> 

<bean name="serviceCallerFactory" class="com.archit.mock.ServiceCallerFactory" /> 

Ошибка:

java.lang.AssertionError: 
    Unexpected method call ServiceCaller.checkValidity("testDriver"): 
    ServiceCaller.checkValidity("testDriver"): expected: 1, actual: 2 
    at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:44) 
    at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:85) 
    at org.easymock.internal.ClassProxyFactory$MockMethodInterceptor.intercept(ClassProxyFactory.java:94) 
    at com.archit.mock.ServiceCaller$$EnhancerByCGLIB$$9848ad9e.checkValidity(<generated>) 
    at com.archit.mock.Car.drive(Car.java:12) 
    at com.archit.mock.CarTest.test2(CarTest.java:60) 
    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:601) 
    at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:66) 
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:312) 
    at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:86) 
    at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:94) 
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:296) 
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:284) 
    at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:84) 
    at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49) 
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:209) 
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:148) 
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:122) 
    at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34) 
    at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44) 
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:120) 
    at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:102) 
    at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53) 
    at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:42) 
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) 
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 

Другие наблюдения:

  • Создание рамки объекта в качестве прототипа в весеннем конфигурации работает нормально.
  • Оба теста при работе индивидуально работают нормально.
  • Основано на значении выше 2, Кажется, проблема с повторной установкой mocks.

ответ

1

Мне стало легче с помощью mocks, чтобы они запускались как новые объекты каждый раз при запуске тестов. Вы можете достичь этого, имея все свои фиктивные объекты в верхней части, как частные переменные, используя Mockito.Mock аннотации:

@Mock 
private MockOneClass mockOne; 
... 
@Mock 
private MockNClass mockN; 

Затем с помощью JUnit Перед аннотацией, создать функцию установки какого-то, что инициализирует все издевается объекты:

@Before 
public void setup() { 
    // initialize all the @Mock objects 
    MockitoAnnotations.initMocks(this); 
} 

Таким образом, перед запуском каждого теста вы получаете новый Mock созданного, который затем можно применить любое количество expects и функциональность, не беспокоясь об освобождении из любых старых насмешливого сделаны в предыдущем контрольная работа. Если у вас есть какой-либо макет, который, как вы знаете, предоставит некоторую определенную функциональность (например, статические однотонные макеты getInstance), вы можете вызвать эту функцию setup, чтобы помочь очистить тесты от сброса Mock.

У меня есть тест, который имеет 10+ тестов, которые запускаются в строке, использующей эту структуру. Это не только облегчает чтение, но и очень быстро устанавливает тесты с нуля. Возможность копировать старые макетные настройки в тестах и ​​удалять/изменять определенные части намного проще, чем при необходимости проверять каждый макет объекта на каждый тест, который просто не расширяется, как только вы начнете получать больше тестов.

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

  • Нет связанных вопросов^_^