Как написать макет объекта? - PullRequest
3 голосов
/ 15 января 2009

Моя первая работа по программированию познакомила меня с модульным тестированием и концепцией фиктивных объектов, но что-то в этом всегда было не так.

Допустим, мы писали банковское приложение, и нам нужно было смоделировать объект BankAccount:


    // boilerplate code
    public interface IBankAccount {
        void Deposit(int amount);
        void Withdrawal(int amount);
        int getBalance();
        int getAccountNumber();
    }

    public interface IBankAccountFactory {
        IBankAccount getAccount(int accountNumber);
    }

    public class ProductionBankAccountFactory implements IBankAccountFactory { 
        public IBankAccount getAccount(int accountNumber) {
            return new RealBankAccount(accountNumber);
        }
    }

    public class MockBankAccountFactory implements IBankAccountFactory {
        public IBankAccount getAccount(int accountNumber) {
            return new MockBankAccount(accountNumber);
        }
    }

    public static class BankAccountFactory {
        // ewww, singletons!
        public static IBankAccountFactory Instance;
    }

    // finally, my actual business objects
    public class MockBankAccount implements IBankAccount {
        public MockBankAccount(int accountNumber) { ... }
        // interface implementation
    }

    public class RealBankAccount implements IBankAccount {
        public RealBankAccount(int accountNumber) { ... }
        // interface implementation
    }

У каждого класса есть цель:

  • Существуют фабричные и фабричные интерфейсы, чтобы связать конструкторы с нашими фиктивными и реальными объектами.
  • Статический класс BankAccountFactory позволяет нам BankAccountFactory.Instance назначить экземпляр IRealBankAccountFactory или MockBankAccountFactory в начале нашего производственного приложения или тестов соответственно.
  • Как только все настроено правильно, любой класс может получить экземпляр IBankAccount, просто вызвав:

    BankAccountFactory.Instance.getAccount(accountNum);

Это работает, но в результате получается много стандартного кода. Мне не нужно было писать 5 новых классов для каждого класса, который я хочу издеваться. Я убежден, что есть более простой способ, поэтому я должен спросить SO-сообщество:

Есть ли лучший или предпочтительный способ написания фиктивных объектов?

[Изменить, чтобы добавить:] Я ценю ссылки на макеты и DI-фреймворки, но сейчас я работаю над приложением 500 KLOC, и по крайней мере 60% кода состоит из Образцовые макеты в стиле выше.

Я просто хочу уменьшить размер кодовой базы без переписывания больших кусков кода для Yet-Another-Framework ™, так что это помогает мне больше видеть ложные классы, написанные от руки. :)

Ответы [ 3 ]

8 голосов
/ 15 января 2009

Лучший способ - попросить кого-нибудь написать. Некоторые варианты здесь:

Мок - http://code.google.com/p/moq/

Rhino Mocks - http://ayende.com/projects/rhino-mocks.aspx

1 голос
/ 15 января 2009

Я думаю, мой первый вопрос: зачем вам использовать фабричный шаблон, чтобы обернуть конструкцию ваших объектов; в частности, ваш объект Mock. Поскольку каждый модульный тест в комплекте должен выполняться полностью независимо от любых других модульных тестов, создается впечатление, что вы можете создать экземпляр своего MockBankAccount непосредственно в методе setUp вашего класса модульного теста или даже в самом тесте. Если бы я был в ситуации выше, я бы написал что-то вроде этого:

public interface IBankAccount {
    void Deposit(int amount);
    void Withdrawal(int amount);
    int getBalance();
    int getAccountNumber();
}

public class MockBankAccountFactory implements IBankAccountFactory {
    public IBankAccount getAccount(int accountNumber) {
        return new MockBankAccount(accountNumber);
    }
}

public class BankAccountUnitTest extends TestCase {
    IBankAccount testBankAccount;

    public void setUp() {
        testBankAccount = new MockBankAccount(someAccountNumber);
    }

    // Unit tests here
}

Если вы используете фабрику для модульного тестирования другого класса, который использует IBankObject, то вам следует изучить внедрение зависимостей , чтобы предоставить фиктивный объект этому классу чем тестируемый класс для создания экземпляра фиктивного объекта.

0 голосов
/ 15 января 2009

Существуют библиотеки Mock, которые упрощают процесс, позволяя указать объект и его поведение в коде модульного тестирования.

Хорошим примером является библиотека Moq (http://code.google.com/p/moq/)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...