[英]How to mock static method that returns final class?
I want to mock next line: 我想模拟下一行:
Bigquery bigquery = Transport.newBigQueryClient(options).build();
The problem here is that newBigQueryClient method returns Bulder class, which is final. 这里的问题是newBigQueryClient方法返回的Bulder类是最终的。 This means that I cannot mock it neither with mockito or powermockito(it returns such exception: Cannot subclass final class), but I need to return something suitable to mock build method on it. 这意味着我既不能使用嘲笑者也不可以使用powermockito来嘲笑它(它返回这样的异常:不能对最终类进行子类化),但是我需要返回适合于模拟其上的构建方法的东西。 Any ideas how to do it? 有什么想法怎么做?
A suggestion to improve your code and making it much more testable: 改善代码并使其更具可测试性的建议:
First of all, you do not mock a statement like the assignment that you gave us as an example. 首先,您不会像您给我们的示例那样模拟声明 。 You mock objects and assign their references to variables whose type represent a super type. 您模拟对象并将其引用分配给其类型表示超类型的变量。
Additionally, if you feel you have to mock something away, you have obviously found a dependency in your code snippet that is an important concept. 另外,如果您觉得自己必须嘲笑某些东西,那么显然您已经在代码片段中找到了一个重要的依赖项。
Make this concept obvious! 使这个概念显而易见!
In your case, you want to get a Bigquery
object and assign its reference to a variable. 对于您的情况,您想获取一个Bigquery
对象并将其引用分配给一个变量。 The unclear concept is that someone has to provide such an object. 不清楚的概念是有人必须提供这样的对象。
Make this concept clear with an interface: 通过一个界面来阐明这个概念:
interface BigqueryProvider {
Bigquery provide(Object options);
}
In your class where you also have the statement 在班上你也有这样的陈述
Bigquery bigquery = Transport.newBigQueryClient(options).build();
you now add the following instance variable 您现在添加以下实例变量
private final BigqueryProvider bigqueryProvider;
and change your constructors accordingly. 并相应地更改您的构造函数。 As I made it final
it must be set at construction time. 正如我final
它必须在构建时设置。 Of course, you must also identify the code where you call the constructors. 当然,您还必须标识调用构造函数的代码。 For that you also need a default implementation: 为此,您还需要一个默认实现:
final class DefaultBigqueryProvider implements BigqueryProvider {
@Override
public Bigquery provide(Object options) {
return Transport.newBigQueryClient(options).build();
}
}
Then change the above mentioned assignment to 然后将上述分配更改为
Bigquery bigquery = bigqueryProvider.provide(options);
Now to the tests: In your tests, you now can provide a test implementation for the provider interface. 现在开始测试:在测试中,您现在可以为提供程序接口提供测试实现。 A mocking framework can easily do that for you. 模拟框架可以轻松为您完成此任务。 You are also able to return a Bigquery
object of your choice, being it an object of that class or of a subclass, it doesn't matter. 您还可以返回自己选择的Bigquery
对象,无论该对象是该类还是子类的对象,都没有关系。
Your test code then instantiates your class by providing them a mocked BigqueryProvider
which you have under full control. 然后,您的测试代码通过为您提供一个完全受控的BigqueryProvider
来实例化您的类。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.