在Java单元测试中,如何mock未注入但在待测class内部创建的变量?

In Java unit testing, how to mock the variables that are not injected but created inside the to-be-tested class?

例如要测试的class是

public class toBeTested {
    private Object variable;

    public toBeTested(){
        variable = someFactory();         // What if this someFactory() sends internet request? 
                                          // Can I mock "variable" without calling 
                                          // someFactory() in testing?
    }

    public void doSomething(){
        ...
        Object returnedValue = variable.someMethod();  // In testing, can I mock the behavior of 
                                                       // this someMethod() method when 
                                                       // "variable" is a private instance 
                                                       // variable that is not injected? 
        
        Object localVariable = new SomeClass();        // Can I mock this "localVariable" in 
                                                       // testing?
        ...
    }
}

我的问题如上评论所述。

简而言之,如何模拟未注入但在待测内部创建的变量class?

提前致谢!

你的问题更多是关于设计的,你的class的设计是错误的,不可测试,写单元测试不容易(有时根本不可能)一种方法和 class 以前开发的。实际上 TDD(测试驱动开发)的一大好处是它可以帮助开发人员以可测试的方式开发他们的组件。

如果先编写测试,您的 class 就不会以这种方式开发。事实上,当你为你的组件编写测试时,你应该做的一件不可避免的事情就是重构。因此,在这里要将您的组件重构为可测试组件,您应该将工厂作为参数传递给 class 的构造函数。

而 localVariable 呢:

这真的取决于你的情况和你对你的单位的期望(这里你的单位是 doSomething 方法)。如果它是一个变量,你从你的方法中提取出来作为它的任务的一部分来创建,并且它应该在每次调用中根据方法中的一些逻辑来创建,那么让它在那里是没有问题的,但是如果它提供了一些其他的逻辑来你的方法,可以作为参数传递给你的 class 你可以把它作为参数传递给你的 class 的 cunstructor。

还有一点,重构的时候要小心,会有很多其他组件使用你的组件,你应该逐步重构,你不应该改变你的方法的逻辑。

添加另一个观点:如果遇到您必须测试给定 class 并且不允许更改您需要测试的 class 的情况,您可以选择使用像 PowerMock (https://github.com/powermock/powermock) 这样的框架来提供增强的模拟功能。

但请注意,不建议仅将 PowerMock 用于证明难以测试代码的合理性。 Tashkhisi 的回答是迄今为止更好的通用方法。