When to use stubs/mocks and when to use real objects in unit testing?

拈花ヽ惹草 提交于 2020-01-05 07:05:11

问题


I recently tried to improve my unit testing skills and read quite some literature about unit testing and I am also trying to realize what I learned in a php-project I am currently developing with phpunit. But I still have a in my opinion very fundamental question how to unit test methods which interact with objects of other classes or even with other methods of the same class.

Is there some rule of thumb or some help how I can decide what dependencies I should stub/mock and for what dependencies I should simply use a normal object? To clarify my question, here is an example code, with different scenarios:

interface DependencyInterface {
    public method dependentMethod() { ... }
}
class Dependency implements DependencyInterface {...}

class ClassUnderTest {
    private $dependency
    public __construct(DependencyInterface $dependency) {
        $this->dependency = dependency;
    }
    public function methodUnderTest() {
        ...
        $result1 = $this->dependency->dependentMethod();
        ...
        $result2 = $this->otherMethod();
        ...
        $result3 = $this->usedInMultiplePublicMethods();
    }

    public function otherMethod() {...}
    private function usedInMultiplePublicMethods() {...}
}

So my questions are now for a unit test which tests the functionality of the method methodUnderTest, should I:

  1. stub the interface DependencyInterface and inject it in the constructor, or should I simply use an instance of the implementation Dependency?
  2. partially stub the class ClassUnderTest itself to deliver a fixed result for otherMethod, since this maybe very complex method has already its own complete unit tests?
  3. I decided to not unit tests private methods, since they are not part of the interface of the class (I know this is a controversial topic and is not the scope of my question). Do I have now to cover for each public method which uses the private method usedInMultiplePublicMethods all possible effects which may occur in the private method? Or should I only test all possible effects in one of the public methods which uses it and stub the private method in the tests for all other public methods?

I am quite not sure about when to use stubbing/mocking and when not.


回答1:


The why of mocking is to be able to write unit test that means a test which is: fast, isolated, repeatable, self validating and Thorough and Timely (F.I.R.S.T)

To be able to test a unit/module in isolation you may need to mock/stub any external module (database access, api call, logging system...).




回答2:


For your points 1 & 2 , rad's answer points to main underlying principles to keep in mind e.g. if you are going to test a logic which is using a database service to fetch data and then doing computations on fetched data, would you mock that database service or use real database service ?

As is clear from objective - you are unit testing logic itself and not database service data fetch so you would mock database service and would assume that database service is giving correct data & you would simply focus on testing logic on computed data. You will have separate tests for database fetching service and that isolation property is all about.

The word unit is significant in that sense that your these tests should be very focused on current logic only by limiting your scope & by not cluttering everything else into it.

This answer is mainly for your points # 3. Its OK to not explicitly test private methods but if you go by basic purpose of unit tests - you wouldn't be much worried about something being private or public. Somewhere down the line, unit testing is for developer self satisfaction too & it would simply make your code more robust if unit tests are written for private methods too.

Just because access level is private doesn't change the basic concept that its a piece of logic that needs testing. Code coverage wise , you might be OK from one public method but I am of view that you should treat calls from different public methods as distinct.

Never forget the basic purpose of unit tests - that you are trying to find errors in your logic, trying to cover all boundary cases & trying to make your code more robust.



来源:https://stackoverflow.com/questions/48176358/when-to-use-stubs-mocks-and-when-to-use-real-objects-in-unit-testing

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!