4

是否可以模拟(当前使用 Mockito,也可能是其他测试库)类中的字段“sf”,如下所示:

public class SomeFilter implements Filter {

   private Logger log = Logger.getLogger(getClass());
   private SomeField sf = new SomeField();

   @Override
   public void init(FilterConfig fc) throws ServletException {
      log.info("");
   }

   @Override
   public void doFilter(ServletRequest req, ServletResponse res, FilterChain fc) throws     IOException, ServletException {
        fc.doFilter(request, response);
   }

   @Override
   public void destroy() {
      log.info("");
   }
}

如果是这样,怎么做?

4

4 回答 4

4

考虑具有一些漂亮特性的PowerMock框架,包括与 Mockito 框架的一些集成

考虑这个示例绕过封装并访问私有字段,如下所示

String sf = Whitebox.getInternalState(o, "sf", String.class, B.class);
Whitebox.setInternalState(o, "sf", "XXX", B.class);

还要考虑(来自最后一个链接):

所有这些事情都可以在不使用 PowerMock 的情况下实现,这只是普通的 Java 反射。然而反射需要很多样板代码并且容易出错,因此 PowerMock 为您提供了这些实用方法。PowerMock 让您可以选择是否重构代码并添加 getter/setter 方法来检查/更改内部状态,或者是否使用其实用程序方法来完成相同的事情而不更改生产代码。由你决定!

于 2012-12-19T09:28:40.860 回答
3

是的。在您的测试类中,您可以使用ReflectionTestUtilsSpring Framework

http://static.springsource.org/spring/docs/2.5.5/api/org/springframework/test/util/ReflectionTestUtils.html

像这样调用setField方法:

SomeFilter filter = new SomeFilter();
SomeField field = Mockito.mock(SomeField.class);
ReflectionTestUtils.setField(filter , "sf", field);

您可以像往常一样在测试用例中模拟对象。

如果不能导入 Spring Framework,直接使用 Java 反射来做同样的事情并不太难。

于 2012-12-19T09:07:16.857 回答
2

我很想制作该字段,protected或者package-private然后在您的测试中注入模拟,例如:

final SomeField sf = mock(SomeField.class);
someFilter.sf = sf;

否则,您可以提供一个构造函数来注入模拟:

...
public SomeFilter() {
   this(new SomeField());
}


public SomeFilter(SomeField sf) {
    this.sf = sf;
}
...

然后在您的测试中,您可以像这样传递模拟:

final SomeField sf = mock(SomeField.class);
SomeFilter someFilter = new SomeFilter(sf);
于 2012-12-19T09:12:46.557 回答
1

您可以使用 PowerMock 模拟 SomeField 类的构造函数。从文档中:

新对象的模拟构造

  1. @RunWith(PowerMockRunner.class)在测试用例的类级别使用注释。@PrepareForTest(ClassThatCreatesTheNewInstance.class)在测试用例的类级别使用 注释。
  2. 用于PowerMock.createMock(NewInstanceClass.class)创建应该构造的类的模拟对象(我们称之为mockObject)。
  3. 用于 PowerMock.expectNew(NewInstanceClass.class).andReturn(mockObject)期望 NewInstanceClass.class 类型的对象的新构造,而是返回模拟对象。
  4. 用于PowerMock.replay(mockObject, NewInstanceClass.class)将模拟对象和类更改为重放模式,或者使用 PowerMock.replayAll()方法。
  5. 用于PowerMock.verify(mockObject, NewInstanceClass.class)更改模拟对象和类的验证模式,或者使用 PowerMock.verifyAll()方法。

如果你想使用带有Mockito 语法的 powermock ,那么它看起来像:

whenNew(MyClass.class).withNoArguments().thenThrow(new IOException("error message"));
于 2013-01-13T20:16:41.007 回答