![](/img/trans.png)
[英]junit4: How to call the other class static method in junit4 @before or @Test?
[英]How can I easily mock out a static method in Java (jUnit4)
如何在Java中轻松模拟静态方法?
我正在使用Spring 2.5和JUnit 4.4
@Service
public class SomeServiceImpl implements SomeService {
public Object doSomething() {
Logger.getLogger(this.class); //a static method invoked.
// ...
}
}
我不控制我的服务需要调用的静态方法,所以我不能将它重构为更可单元测试。 我使用Log4J Logger作为示例,但真正的静态方法类似。 不能更改静态方法。
做Grails工作,我习惯使用类似的东西:
def mockedControl = mockFor(Logger)
mockControl.demand.static.getLogger{Class clazz-> … }
…
mockControl.verify()
我如何在Java中做类似的事情?
你是说你无法控制主叫代码吗? 因为如果您控制对静态方法的调用而不是实现本身的调用,则可以轻松地使其成为可测试的。 使用与静态方法具有相同签名的单个方法创建依赖关系接口。 您的生产实现只会调用静态方法,但当前调用静态方法的任何内容都将通过接口调用。
然后,您可以以正常方式模拟该接口。
JMockit框架承诺允许模拟静态方法。
事实上,它提出了一些相当大胆的主张,包括静态方法是一种完全有效的设计选择,并且由于测试框架的不足,它们的使用不应受到限制。
无论这些声明是否合理,JMockit框架本身都非常有趣,尽管我还没有尝试过。
public interface LoggerWrapper {
public Logger getLogger(Class<?> c);
}
public class RealLoggerWrapper implements LoggerWrapper {
public Logger getLogger(Class<?> c) {return Logger.getLogger(c);}
}
public class MockLoggerWrapper implements LoggerWrapper {
public Logger getLogger(Class<?> c) {return somethingElse;}
}
正如上面提到的另一个答案, JMockit可以模拟静态方法(以及其他任何东西)。
它甚至直接支持日志记录框架。 例如,你可以写:
@UsingMocksAndStubs(Log4jMocks.class)
public class SomeServiceTest
{
// All test methods in this class will have any calls
// to the Log4J API automatically stubbed out.
}
但是,对JUnit 4.4的支持被删除了。 支持JUnit 3.8,JUnit 4.5+和TestNG 5.8+。
这是静态方法不好的原因之一。
我们为大多数工厂重新设计了setter,以便我们可以将mock对象设置到它们中。 实际上,我们提出了一些接近依赖注入的东西,其中一个方法充当了我们所有单身人士的工厂。
在您的情况下,添加Logger.setLogger()方法(并存储该值)可能会起作用。 如果必须,您可以扩展记录器类并使用您自己的方法遮蔽getLogger方法。
您可以使用AspectJ拦截静态方法调用并为测试执行一些有用的操作。
基本上,目前在Java + Spring 2.5和JUnit 4.4中没有一种简单的方法可以做到这一点。
虽然可以重构和抽象静态调用,但重构代码并不是我正在寻找的解决方案。
JMockit看起来会起作用,但与Spring 2.5和JUnit 4.4不兼容。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.