简体   繁体   English

如何模拟返回最终类的静态方法?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM