我应该如何使用EasyMock的@Mock注释(3.2版中的新功能)?

时间:2013-08-12 20:10:35

标签: java junit4 easymock

看起来EasyMock 3.2版现在支持使用注释来设置模拟对象。我是EasyMock(以及Java)的新手,我正在尝试了解如何使用它。这些注释是做新事物还是只提供另一种做事方式? documentation说:

  

从EasyMock 3.2开始,现在可以使用注释创建模拟。这很好   以及创建模拟并将其注入测试类的更短方法。   以下是上面的示例,现在使用注释:...

然后有一个列表显示@TestSubject和@Mock注释的使用,但我不明白它是如何工作的。似乎它将被测试类的私有字段神奇地设置为模拟对象。在我的大多数情况下,我只想制作返回预定义值的模拟对象,以便在JUnit测试用例中使用(目前不关心验证调用哪些,调用它们的次数等)。例如,对于某些测试,我想创建一个假的HttpServletRequest对象,如下所示:

public class SomeTest {
    // Construct mock object for typical HTTP request for the URL below 
    private static final String REQUEST_URL = "http://www.example.com/path/to/file?query=1&b=2#some-fragment";
    private static final Map<String, String> requestHeaderMap;
    static {
        Map<String, String> requestHeaders = new LinkedHashMap<String, String>();
        requestHeaders.put("host", "www.example.com");
        // ... (add any other desired headers here) ...
        requestHeaderMap = Collections.unmodifiableMap(requestHeaders);
    }

    private HttpServletRequest httpServletRequest;
    // ...

    @Before
    public void setUp() throws Exception {            
        httpServletRequest = createNiceMock(HttpServletRequest.class);
        expect(httpServletRequest.getRequestURI()).andReturn(REQUEST_URL).anyTimes();
        expect(httpServletRequest.getHeaderNames()).andReturn(Collections.enumeration(requestHeaderMap.keySet())).anyTimes();
        capturedString = new Capture<String>();
        expect(httpServletRequest.getHeader(capture(capturedString))).andAnswer(new IAnswer<String>() {
            public String answer() throws Throwable {
                String headerName = capturedString.getValue().toLowerCase();
                if (requestHeaderMap.containsKey(headerName))
                    return requestHeaderMap.get(headerName);
                else 
                    return "";
            }
        }).anyTimes();

        replay(httpServletRequest);

        // ...
    }

    @Test
    public void someMethod_givenAnHttpServletRequest_shouldDoSomething() {
        // ...
    }
}

我可以更改上面的代码来使用注释吗?如果是的话,我应该吗?在什么情况下?

我认为将@Mock注释放在实例变量声明之上会自动处理createNiceMock(...)部分,但这似乎不起作用,所以我怀疑我误解了一些东西。

1 个答案:

答案 0 :(得分:2)

检查他们的源代码,他们使用反射将任何带有@Mock的内容注入到@TestSubject的字段中。他们的方法的javadoc

public static void injectMocks(final Object obj)
EasyMockSupport.java中的

说:

  

将模拟注入到参数中传递的类中使用{@link Mock}注释的每个字段。然后,将这些模拟注入到使用TestSubject注释的每个类的字段中。

     

规则是

     
      
  • 忽略静态和最终字段
  •   
  • 如果可以将模拟分配给字段,请执行此操作。同一个模拟被分配不止一次
  •   
  • 如果没有可以为某个字段分配模拟,请以静默方式跳过
  •   
  • 如果可以为同一字段分配两个模拟,则返回错误
  •   
  • 在超类
  • 上递归搜索字段   
     

注意:如果参数扩展了EasyMockSupport,将使用它创建模拟以允许replayAll / verifyAll随后工作

     

@param obj注入模拟的对象

     

@since 3.2

     

public static void injectMocks(final Object obj){         ...   }

为了使用@Mock注释,你需要一个@TestSubject,它有一个HttpServletRequest字段,供EasyMock设置@Mock on(通过反射)。提供注释是为了使测试更容易,它让你跳过createMock,然后自己调用定居者。