JUnit与Mockito,EasyMock等嘲笑
我正在尝试在我正在测试的类中模拟一个对象的方法。
例如
class ClassToTest { public doSomething () { SomeObject a = new SomeObject (); a.doSomethingElse (); } }
有没有办法模拟变量“a”的方法? 我想doSomethingElse在测试期间什么都不做。 我目前正在使用Mockito,但我对任何模拟框架持开放态度。
谢谢
是的,有一种方法,如下面的JMockit测试所示:
public void testDoSomething(final SomeObject mock) { new ClassToTest().doSomething(); new Verifications() {{ mock.doSomethingElse(); }}; }
无需重构测试代码以使用包装器,DI等; 简单地模仿你需要被嘲笑的东西。
当它被声明为局部变量时,不可能模仿引用“a”,就像你的情况一样。 您可以考虑将依赖项注入SomeObject,例如作为doSomething方法的参数。 这样,您可以在测试中注入SomeObject的模拟。
dependency injection的一个好处是提高了可测试性 。
通过一些重构,当然可以:
class SomeObject { public void doSomethingElse() { } } class ClassToTest { private final SomeObject someObject; public void doSomething() { someObject.doSomethingElse(); } public ClassToTest(SomeObject someObject) { this.someObject = someObject; } } class Test { @Test public void testDoSomething() { SomeObject someObject = Mockito.mock(SomeObject.class); new ClassToTest(someObject).doSomething(); Mockito.verify(someObject, Mockito.atLeastOnce()).doSomethingElse(); } }
我相信你可以为EasyMock 2.5或更早版本使用EasyMock Class Extensions ,显然它包含在3.0中。 有关您要执行的操作的信息,请参见上一页的这一部分 。 也就是说,我没有亲自尝试过这样做,所以我不知道它会有多好用。
如果你想在每个调用中有一个新实例,我建议用以下方式重构:
class ClassToTest { public doSomething () { SomeObject a = getInstance(); a.doSomethingElse (); } protected SomeObject getInstance() { return new SomeObject(); } }
然后,您可以创建一个扩展ClassToTest的测试类,覆盖getInstance()方法,其中一个提供模拟对象。
这当然只有在暴露getInstance()方法时才可行,所以如果该类是公共API的一部分,我不推荐它。 如果是这种情况,请考虑使用dependency injection提供工厂类。
class ClassToTest { private SomethingElseInterface somethingElseDoer ; public ClassToTest(SomethingElseInterface somethingElseDoer) { this.somethingElseDoer = somethingElseDoer; } public doSomething () { somethingElseDoer.doSomethingElse(); } }
在哪里使用它:
SomethingElseInterface somethingElseDoer = ...; // in a test, this is where you mock it ClassToTest foo = new ClassToTest(somethingElseDoer); // inject through constructor foo.doSomething();