Why is it so bad to mock classes?

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

He says that only interfaces need to be spoofed, otherwise this is an architecture error.

I wonder why this expression (I fully trust him) is so true? I do not know this and I want to be sure.

Did I miss the mockery (yes, I read Martin Fowler's article )

+39
unit-testing testing mocking
Oct 20 '09 at 14:47
source share
8 answers

Mocking is used to test the protocol - it checks how you will use the API, and how you will respond when the API responds accordingly.

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

From a practical point of view, mocking frameworks tend to have limitations regarding mocking classes.

In my experience, the mockery is somewhat confusing - often you are not interested in the exact interaction, you really want a stub ... but the mocking structure can be used to create stubs, and you fall into the trap of creating fragile tests, mocking, instead of knocking. It is a tough balance to get right, though.

+55
Oct 20 '09 at 14:52
source share

IMHO, which means your colleague, is that you should program the interface, not the implementation . If you find mocking classes too often, this is a sign that you have violated the previous principle when designing your architecture.

+18
Oct 20 '09 at 2:55
source share

Measuring classes (as opposed to mocking interfaces) are bad because the layout still has a real class in the background, it is inherited from, and it is possible that the real implementation is executed during the test .

When you mock an interface (either a stub or some other), there is no risk of executing the code that you really wanted to make fun of.

Worn classes also force you to do everything that could be mocked, to be virtual , which is very intrusive and can lead to poor class design .. p>

If you want to separate classes, they should not know each other, this is the reason why it makes sense to ridicule (or a stub or something else) one of them. So in any case, it is recommended to use against interfaces, but it is mentioned here by others.

+12
Oct. 20 '09 at 2:59 p.m.
source share

Typically, you want to mock an interface.

While you can make fun of a regular class, it affects the design of your class too much to test. Concern, like accessibility, regardless of whether the method is virtual, etc., will be determined by the ability to mock the class , and not with the true problems of OO.

There is one false library called TypeMock Isolator, which allows you to circumvent these restrictions (there is a cake, there is a cake), but it is quite expensive. It’s better to design for verification.

+4
Oct 20 '09 at 14:52
source share

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

+3
Sep 28 '14 at 8:08
source share

Change Since you clarified that your colleague meant that the mock class is bad, but the mock interface is not specified, the answer below is deprecated. You should refer to this answer .

I am talking about mock and stub as defined by Martin Fowler , and I assume that your colleague also meant it.

Failure is bad because it can lead to excessive test validation. Use a blank if possible and avoid layout.

Here is the difference between mock and stub (from the above article):

Then we can use a state check on a stub like this.

class OrderStateTester... public void testOrderSendsMailIfUnfilled() { Order order = new Order(TALISKER, 51); MailServiceStub mailer = new MailServiceStub(); order.setMailer(mailer); order.fill(warehouse); assertEquals(1, mailer.numberSent()); } 

Of course, this is a very simple test - only the message is sent. We did not test it by sending a human right or with the right content, but this will be shown to illustrate the point.

Using mocks this test will look completely different.

 class OrderInteractionTester... public void testOrderSendsMailIfUnfilled() { Order order = new Order(TALISKER, 51); Mock warehouse = mock(Warehouse.class); Mock mailer = mock(MailService.class); order.setMailer((MailService) mailer.proxy()); mailer.expects(once()).method("send"); warehouse.expects(once()).method("hasInventory") .withAnyArguments() .will(returnValue(false)); order.fill((Warehouse) warehouse.proxy()); } } 

To use the state check on the stub, I need to do some additional methods on the> stub to help with the check. As a result, the stub implements MailService, but adds additional> testing methods.

+2
Oct. 20 '09 at 14:50
source share

The answer, like most practice questions, "depends on this."

Excessive use of mock-ups can lead to trials that don't actually test anything. It can also lead to tests that are virtual re-implementations of the test code that are closely related to a particular implementation.

On the other hand, the wise use of mock-ups and stubs can lead to unit tests that are neatly isolated and test one and only one thing - that’s good.

All about moderation.

0
Oct 20 '09 at 14:53
source share

It makes sense to swing classes, so tests can be written early in the development life cycle.

There is a tendency to continue to use mock classes, even when specific implementations become available. There is also a tendency to develop against the false classes (and stubs) needed at the start of the project when some parts of the system were not built.

After a part of the system has been built, it is necessary to test it and continue testing against it (for regression). In this case, starting with mocks is good, but they should be discarded in favor of the implementation as soon as possible. I saw the fight projects because different teams continue to develop against the behavior of the layout, and not the implementation (after its appearance).

When testing for layouts, you assume that the layout is specific to the system. Often this involves guessing what the mocking component will do. If you have a specification of the system you are kidding, you need not guess, but often the as-built system does not meet the original specification due to practical considerations found during construction. Flexible development projects assume this will always happen.

Then you develop code that works with the layout. When it turns out that the layout does not really reflect the behavior of the real embedded system (for example, latency problems that are not observed in problems with layouts, resources and efficiency that are not observed in layouts, concurrency problems, performance problems, etc.), you then have a bunch of useless tantalizing tests that you should now support.

I believe that the use of layouts is valuable at the beginning of development, but these bullying should not contribute to the scope of the project. It is best later if the mockery is removed and the correct integration tests are created to replace them, otherwise your system will not be tested for many conditions that your layout did not imitate (or imitates incorrectly relative to a real system).

So the question is whether to use mocks, whether to use them, and when to remove them.

0
Oct 27 2018-10-27
source share



All Articles