Java单元测试-模拟所有类方法以返回一个结果



我想模拟一个类上的所有方法以返回一个结果,而不是分别模拟每个方法,比如:

mock(Foo.class, allMethodsWithAnyArgs).thenReturn('abc');

我是Java测试的新手,所以请原谅这个愚蠢的问题。这个巨大的项目有Mockito,PowerMockito、PowerMock、EasyMock,可能还有其他东西,所以我可以使用任何推荐的东西。

一个扩展的例子是这样的,我需要测试Foo:

public class Foo {
doSomething(){
Bar bar = new bar();
// some code
bar.x(a);
// some code
bar.x(a, b, c);
// some more code
bar.y(...);
// even more code
bar.z(...);
}
}

我需要拦截所有的酒吧电话,但不在乎回报,或者我想要相同的回报,比如说他们所有人的1或"ok",等等。

更新:我同意这不是最好的测试代码,这里是我在这种情况下尝试测试的最新示例,所以我需要存根MyUtil和bar方法,它们是静态的,所以你建议我如何重构它们?对我来说,把MyUtil作为一个必要的参数是没有意义的,如果可能的话,我更愿意让Foo保持静态。一个有效的测试文件将不胜感激,因为我已经在这种事情上挣扎了几天了。

public class Foo {
public static Object doSomething(Long id){
Bar bar = new Bar();
Object obj;
if(somecondition) {
Long vnumber = MyUtil.getVNumber(id);
obj = bar.getCurrentObj(id, vnumber);            
} else {
obj = bar.getPreviousObj(id);
}
bar.z(obj);
....
}
}

此外,这个类的一个要点是使它成为一个黑盒,我不希望被调用方担心创建实例并将其传入,甚至不希望知道事情是如何工作的,我只想传递一个ID并获得它的结果。例如,一些调用函数甚至无法访问Bar,所以我不能将其作为必需的参数。

有这么多方法要模拟可能是一个类有太多责任的迹象。

然而,mock并不是唯一的测试替身。可能更适合您的用例的是假的。

这实际上取决于Foo在一个接口后面:

interface Bar {

String x(String s);

String y(String s);
}

然后你就有了你的产品实现:

class RealBar implements Bar {
@Override
String x(String s) {
// whatever your production logic is
}
}

然后你在test源集中的测试中使用的一个赝品:

class FakeBar implements Bar {
@Override
String x(String s) {
return "abc";
}
}

因为这个赝品是开箱即用的,所以你可以重用它,而不必手动为它存根行为

如果您在Foo中使用构造函数注入,那么您的测试将包括传入伪造的Bar,而不是生成的Bar

@Before
public void setUp() {
foo = new Foo(new FakeBar());
}

因此,伪造是避免手动清除负担的公认方式。

然而,如果除了存根化类的每个方法以返回相同的值之外别无选择,那么这不是一个常见的用例,大多数mocking库也不太可能支持它。尤其是当Mockito试图在类设计上固执己见,以防止您编写次优代码时。

可以手动编写代码,使用反射来查找声明的方法,然后存根行为。当你这样做的时候,可能已经执行了"提取接口"并写了一个假的。