英文:
How to mock a method whose object is initialized outside of the testing method?
问题
我有一个类如下:
public class Authentication {
private Timer timer;
public Authentication(){
// 构造函数
}
public void authenticate(){
// 在此方法中初始化计时器
timer = new RouterTimer(FAKE_PARAM);
testingMethod();
}
@VisibleForTesting
void testingMethod(){
timer.method();
// 其他操作
}
}
我有一个 Timer 对象作为类属性,但它并没有在构造函数中初始化,而是在 authenticate() 方法中进行初始化。
我正在为 testingMethod()
编写单元测试,但测试失败,因为 timer
为 null,调用 method()
方法会抛出空指针异常。我无法通过类的构造函数来初始化计时器。我也不能调用 authenticate()
方法来初始化,因为该方法会调用 testingMethod()
。
在这种情况下,我该如何进行模拟或采取其他措施?
英文:
I have a class as
public class Authentication {
private Timer timer;
public Authentication(){
// constructor
}
public void authenticate(){
// Initialize timer in this method
timer = new RouterTimer(FAKE_PARAM);
testingMethod();
}
@VisibleForTesting
void testingMethod(){
timer.method();
// other stuff
}
}
I have a Timer object as a class attribute, but it isn't initialized in constructor, it gets initialized in authenticate().
I'm writing unit test for testingMethod()
, but the tests failed because the timer
is null and calling the method() will throw an NullPointerException. I can't get the timer initialized with the constructor of the class. I can't call authenticate()
to initialize because that method will call testingMethod()
.
How do I mock or do something else in this case?
答案1
得分: 1
为什么要尝试测试私有方法?将您的代码拆分成逻辑部分并分别进行测试。此外,您正在违反SRP(单一职责原则)(https://en.wikipedia.org/wiki/Single-responsibility_principle)。方法authenticate()不应初始化任何内容。
英文:
Why are you trying to test private method? Split your code into logical parts and test them separately. Moreover, you are breaking SRP (https://en.wikipedia.org/wiki/Single-responsibility_principle). Method authenticate() should not initialize anything.
答案2
得分: 1
通常情况下,您不会直接对私有方法进行单元测试。由于它们是私有的,请将它们视为实现细节。没有人会调用其中之一并期望它按特定方式工作。您应该测试公共接口。如果调用私有方法的方法按预期工作,则可以假定您的私有方法也在正确地工作。
英文:
You generally don't unit test private methods directly. Since they are private, consider them an implementation detail. Nobody is ever going to call one of them and expect it to work a particular way.
You should instead test your public interface. If the methods that call your private methods are working as you expect, you then assume by extension that your private methods are working correctly.
答案3
得分: 0
你可以将构造函数修改为接收一个 Timer 对象,这应该由在代码中创建此类实例的上一层提供。
在你的测试中,你可以创建一个模拟的 Timer 对象,并在创建类实例时将其传递。
public class Authentication {
private Timer timer;
public Authentication(Timer timer){
this.timer = timer;
// 构造函数
}
public void authenticate(){
// 在此方法中初始化 timer
timer = new RouterTimer(FAKE_PARAM);
testingMethod();
}
@VisibleForTesting
void testingMethod(){
timer.method();
// 其他内容
}
}
在测试中,使用 Mockito 创建模拟的 Timer,并通过构造函数传递它。
Timer mockTimer = Mockito.mock(Timer.class);
Authentication auth = new Authentication(mockTimer);
英文:
You can change your constructor to receive a Timer object and that should be provided by the upper level where this class instance is created in the code.
In your test, you can create a mock Timer object and pass it when you create the class instance.
public class Authentication {
private Timer timer;
public Authentication(Timer timer){
this.timer = timer;
// constructor
}
public void authenticate(){
// Initialize timer in this method
timer = new RouterTimer(FAKE_PARAM);
testingMethod();
}
@VisibleForTesting
void testingMethod(){
timer.method();
// other stuff
}
}
In the test, create mock timer using Mockito and pass it via constructor
Timer mockTimer = Mockito.mock(Timer.class);
Authentication auth = new Authentication(mockTimer);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论