如何模拟在测试方法外部初始化的对象的方法?

huangapple go评论82阅读模式
英文:

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);

huangapple
  • 本文由 发表于 2020年10月14日 14:28:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/64347725.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定