【问题标题】:How do I mock static methods in a class with easymock?如何使用easymock模拟类中的静态方法?
【发布时间】:2011-03-10 21:43:38
【问题描述】:

假设我有这样的课程:

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

如何使用 easy mock 模拟静态方法调用? StaticDude.getGroove().

我使用的是easy mock 3.0

【问题讨论】:

    标签: java unit-testing static tdd easymock


    【解决方案1】:

    不确定如何使用纯 EasyMock,但可以考虑使用 EasyMock 的 PowerMock 扩展。

    它有很多很酷的功能可以满足您的需求 - https://github.com/jayway/powermock/wiki/MockStatic

    【讨论】:

      【解决方案2】:

      Easymock 是“用于接口(以及通过类扩展的对象)”的测试框架,因此您可以在没有接口的情况下模拟类。考虑为您的静态类创建一个带有访问器的接口对象,然后模拟该访问器。

      编辑:顺便说一句,我不建议做静态类。如果你在做 TDD,最好把所有东西都接口起来。

      【讨论】:

        【解决方案3】:

        以防万一 PowerMock 因任何原因不可用:

        您可以将静态调用移动到一个方法,在测试类中的被测类的实例化中覆盖该方法,在测试类中创建一个本地接口并在被覆盖的方法中使用其方法:

        private interface IMocker 
        {
            boolean doSomething();
        }
        
        IMocker imocker = EasyMock.createMock(IMocker.class);
        
        ...
        
        @Override
        void doSomething()
        {
             imocker.doSomething();
        }
        
        ...
        
        EasyMock.expect(imocker.doSomething()).andReturn(true);
        

        【讨论】:

        • 这样一来,就必须为了测试而更改生产代码。
        【解决方案4】:

        一般来说,不使用某种访问器就无法模拟静态方法,这似乎违背了使用静态方法的目的。这可能非常令人沮丧。

        我知道有一个名为“TypeMock Isolator”的工具,它使用某种撒旦魔法来模拟静态方法,但该工具非常昂贵。

        问题是,我不知道如何覆盖静态方法。您不能将其声明为虚拟的。您不能将其包含在界面中。

        对不起,我是个消极的人。

        【讨论】:

          【解决方案5】:

          添加一个示例,说明如何使用 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" 作为返回。


          使用 EasyMock 进行 Junit 测试,仅模拟注入的 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);
              }
          }
          

          使用 EasyMock 和 PowerMock 进行 Junit 测试,模拟注入的 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);
              }
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2017-05-19
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-12-05
            • 1970-01-01
            相关资源
            最近更新 更多