Почему это настолько плохо для насмешки классов?

Хорошее использование константы для ключей пар ключ/значение. Например, при тихом использовании AppSetting (вместо ApplicationSettings), он действительно не имеет смысла к загрузка название ключа к параметру конфигурации. Если это используется в нескольких местах, засуньте Ключ в константе

45
задан Avdi 20 October 2009 в 14:55
поделиться

6 ответов

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.

61
ответ дан 26 November 2019 в 21:02
поделиться

IMHO, what your colleague means is that you should program to an interface, not an implementation. If you find yourself mocking classes too often, it's a sign you broke the previous principle when designing your architecture.

24
ответ дан 26 November 2019 в 21:02
поделиться

Mocking classes (in contrast to mocking interfaces) is bad because the mock still has a real class in the background, it is inherited from, and it is possible that real implementation is executed during the test.

When you mock (or stub or whatever) an interface, there is no risk of having code executed you actually wanted to mock.

Mocking classes also forces you to make everything, that could possibly be mocked, to be virtual, which is very intrusive and could lead to bad class design.

If you want to decouple classes, they should not know each other, this is the reason why it makes sense to mock (or stub or whatever) one of them. So implementing against interfaces is recommended anyway, but this is mentioned here by others enough.

15
ответ дан 26 November 2019 в 21:02
поделиться

Обычно вы хотите имитировать интерфейс.

Хотя издевательство над обычным классом возможно, оно имеет тенденцию слишком сильно влиять на дизайн вашего класса , чтобы его можно было проверить. Такие проблемы, как доступность , виртуальный метод или нет, и т. Д., Будут определяться способностью имитировать класс , а не истинными проблемами объектно-ориентированного программирования.

Существует одна фальшивая библиотека под названием TypeMock Isolator, которая позволяет обойти эти ограничения (съесть торт, съесть торт), но это довольно дорого. Лучше проектировать для проверки.

4
ответ дан 26 November 2019 в 21:02
поделиться

Edit: Since you have clarified that your colleague meant mock class is bad but mock interface is not, the answer below is outdated. You should refer to this answer.

I am talking about mock and stub as defined by Martin Fowler, and I assume that's what your colleague meant, too.

Mocking is bad because it can lead to overspecification of tests. Use stub if possible and avoid mock.

Here's the diff between mock and stub (from the above article):

We can then use state verification on the 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 that a message has been sent. We've not tested it was send to the right person, or with the right contents, but it will do to illustrate the point.

Using mocks this test would look quite 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 ((Склад) inventory.proxy ());
 }
}

In order to use state verification on the stub, I need to make some extra methods on the >stub to help with verification. As a result the stub implements MailService but adds extra >test methods.

2
ответ дан 26 November 2019 в 21:02
поделиться

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.

1
ответ дан 26 November 2019 в 21:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: