Как написать модульный тест, используя макет объекта? - PullRequest
4 голосов
/ 09 декабря 2010

Чем больше я читаю ложный пример, тем больше я запутываюсь ...

У меня есть метод classA eat (), который вызывает класс FatDude eatThemAll ()

public class classA {

   FatDude dude = new FatDude();

   public String eat() {
        String result = dude.eatThemAll();
   }
}

public class FatDude {
   public String eatThemAll() {
       return "never full";
   }
}

Теперь я хочудля проверки метода класса eatA), насмехаясь над классом FatDude.

public class MockFatDude extends FatDude {
   //override
   public String eatThemAll() {
      return "very full";
   }
}
-------------  test --------------
public class DoTest {

    public void runTest() {
         classA cl = new ClassA();
         String out = cl.eat();
         assertEqual(out, "very full");
    }
}

Этот DoTest runTest (), конечно, не будет использовать класс MockFatDude.Один из способов, которым я могу воспользоваться, - это изменить код так, чтобы он передавал метод FatDude для eat () класса Class, например:

public class classA {

       public String eat(FatDude dude) {
            String result = dude.eatThemAll();
       }
   }

Затем измените мой метод тестирования на:

public class DoTest {

        public void runTest() {
             classA cl = new ClassA();
             String out = cl.eat(new MockFatDude());
             assertEqual(out, "very full");
        }
    }

видите, я должен был изменить исходный код для удовлетворения моих потребностей.Это правильный способ сделать?Что если мне не разрешено менять исходный код?Я знаю, что если я применю концепцию TDD, то можно изменить исходный код, но я хотел бы услышать мнение или совет, если то, что я показал выше, является правильным способом.

Ответы [ 2 ]

4 голосов
/ 09 декабря 2010

Mocking и Принцип инверсии зависимостей (DIP) идут рука об руку, и в большинстве языков Mocks работают лучше всего, развязывая классы с помощью интерфейсов.

В вашем случае этобудет работать без необходимости изменения кода: (Редактировать: я имею в виду, что в будущем, если вы создадите свое приложение таким образом, вам не нужно будет изменять код, чтобы имитировать зависимости:))

  • Аннотацияинтерфейс IDude
  • Конкретные классы FatDude (и MockFatDude) должны реализовывать интерфейс IDude
  • предоставлять механизм для экземпляра IDude, который «устанавливается» или внедряется в classA - Dependency Injection (конструктор или get /комплекты);или шаблон локатора службы лучше всего работают (для замены конкретного класса классов)

Также обратите внимание, что многие фальшивые фреймворки фактически позволяют создавать конкретный класс Mock «на лету» (см. MoQ и др.),так что вы можете создать функциональность MockFatDude прямо в модульном тесте.

2 голосов
/ 09 декабря 2010

Да. Вы наткнулись на хороший дизайн прямо из-за вашего юнит-теста. Если вы посмотрите более внимательно, вы увидите, что вы удалили связь между classA и FatDude. Теперь FatDude может быть интерфейсом для поведения, которое передается при необходимости. ClassA не нужно знать, какой тип FatDude он получает или как создать FatDude (с чизбургерами?).

Ваше решение - именно то, что я бы сделал. Нет ничего плохого в том, чтобы изменить свой код для соответствия TDD, если вы понимаете причины и преимущества / недостатки таких изменений.

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