Why is it so bad to mock classes?

前端 未结 9 1860
一向
一向 2020-12-07 17:57

I recently discussed with a colleague about mocking. He said that mocking classes is very bad and should not be done, only in few cases.

He says that only interfaces

相关标签:
9条回答
  • 2020-12-07 18:01

    Generally you'd want to mock an interface.

    While it is possible to mock a regular class, it tends to influence your class design too much for testability. Concerns like accessibility, whether or not a method is virtual, etc. will all be determined by the ability to mock the class, rather than true OO concerns.

    There is one faking library called TypeMock Isolator that allows you to get around these limitations (have cake, eat cake) but it's pretty expensive. Better to design for testability.

    0 讨论(0)
  • 2020-12-07 18:04

    I would suggest to stay away from mocking frameworks as far as possible. At the same time, I would recommend to use mock/fake objects for testing, as much as possible. The trick here is that you should create built-in fake objects together with real objects. I explain it more in detail in a blog post I wrote about it: http://www.yegor256.com/2014/09/23/built-in-fake-objects.html

    0 讨论(0)
  • 2020-12-07 18:04

    It makes sense to mock classes so tests can be written early in the development lifecycle.

    There is a tendency to continue to use mock classes even when concrete implementations become available. There is also the tendency to develop against mock classes (and stubs) necessary early in a project when some parts of the system have not been built.

    Once a piece of the system has been built it is necessary to test against it and continue to test against it (for regression). In this case starting with mocks is good but they should be discarded in favour of the implementation as soon as possible. I have seen projects struggle because different teams continue to develop against the behaviour of the mock rather than the implementation (once it is available).

    By testing against mocks you are assuming that the mock is characteristic of the system. Often this involves guessing what the mocked component will do. If you have a specification of the system you are mocking then you don't have to guess, but often the 'as-built' system doesn't match the original specification due to practical considerations discovered during construction. Agile development projects assume this will always happen.

    You then develop code that works with the mock. When it turns out that the mock does not truly represent the behaviour of the real as-built system (eg. latency issues not seen in the mock, resource and efficiency issues not seen in the mock, concurrency issues, performance issues etc) you then have a bunch of worthless mocking tests you must now maintain.

    I consider the use of mocks to be valuable at the start of development but these mocks should not contribute to project coverage. It is best later if the mocks are removed and proper integration tests are created to replace them otherwise your system will not be getting tested for the variety of conditions which your mock did not simulate (or simulates incorrectly relative to the real system).

    So, the question is whether or not to use mocks, it is a matter of when to use them and when to remove them.

    0 讨论(0)
  • 2020-12-07 18:09

    The answer, like most questions about practices, is "it depends".

    Overuse of mocks can lead to tests that don't really test anything. It can also lead to tests which are virtual re-implementations of the code under test, tightly bound to a specific implementation.

    On the other hand, judicious use of mocks and stubs can lead to unit tests which are neatly isolated and test one thing and one thing alone - which is a good thing.

    It's all about moderation.

    0 讨论(0)
  • 2020-12-07 18:10

    It depends how often you use (or are forced by bad design) mocks.

    If instantiating the object becomes too hard (and it happens more than often), then it is a sign the code may need some serious refactoring or change in design (builder? factory?).

    When you mock everything you end up with tests that know everything about your implementation (white box testing). Your tests no longer document how to use the system - they are basically a mirror of its implementation.

    And then comes potential code refactoring.. From my experience it's one of the biggest issues related to overmocking. It becomes painful and takes time, lots of it. Some developers become fearful of refactoring their code knowing how long will it take. There is also question of purpose - if everything is mocked, are we really testing the production code?

    Mocks of course tend to violate DRY principle by duplicating code in two places: once in the production code and once in the tests. Therefore, as I mentioned before, any change to code has to be made in two places (if tests aren't written well, it can be in more than that..).

    0 讨论(0)
  • 2020-12-07 18:13

    Mocking is used for protocol testing - it tests how you'll use an API, and how you'll react when the API reacts accordingly.

    Ideally (in many cases at least), that API should be specified as an interface rather than a class - an interface defines a protocol, a class defines at least part of an implementation.

    On a practical note, mocking frameworks tend to have limitations around mocking classes.

    In my experience, mocking is somewhat overused - often you're not really interested in the exact interaction, you really want a stub... but mocking framework can be used to create stubs, and you fall into the trap of creating brittle tests by mocking instead of stubbing. It's a hard balance to get right though.

    0 讨论(0)
提交回复
热议问题