JUnit издевается с Mockito, EasyMock и т. Д. - PullRequest
4 голосов
/ 14 октября 2010

Я пытаюсь смоделировать метод объекта внутри класса, который я тестирую.

Например

class ClassToTest {
   public doSomething () {
       SomeObject a = new SomeObject ();
       a.doSomethingElse ();
   }
}

Есть ли способ издеваться над методами переменной "а"? Я бы хотел, чтобы doSomethingElse ничего не делал во время тестирования. В настоящее время я использую Mockito, но я открыт для любых фальшивых фреймворков.

Спасибо

Ответы [ 6 ]

2 голосов
/ 15 февраля 2011

Да, есть способ, как показано следующим JMockit test:

public void testDoSomething(final SomeObject mock)
{
    new ClassToTest().doSomething();

    new Verifications() {{ mock.doSomethingElse(); }};
}

Нет необходимости рефакторинга тестируемого кода для использования оболочки, DI и т.д .; просто издевайся над тем, что тебе нужно надругаться.

2 голосов
/ 14 октября 2010

При некотором рефакторинге возможно, конечно:

class SomeObject {
    public void doSomethingElse()
    {

    }
}

class ClassToTest
{
    private final SomeObject someObject;

    public void doSomething()
    {
        someObject.doSomethingElse();
    }

    public ClassToTest(SomeObject someObject)
    {
        this.someObject = someObject;
    }
}

class Test {
    @Test
    public void testDoSomething()
    {
        SomeObject someObject = Mockito.mock(SomeObject.class);
        new ClassToTest(someObject).doSomething();
        Mockito.verify(someObject, Mockito.atLeastOnce()).doSomethingElse();
    }
}
2 голосов
/ 14 октября 2010

Невозможно смоделировать ссылку "a", когда она объявлена ​​как локальная переменная, как в вашем случае.Вы могли бы рассмотреть введение зависимости к SomeObject, например, в качестве параметра метода doSomething.Таким образом, вместо этого вы можете ввести в тест макет SomeObject.

Одним из преимуществ внедрения зависимостей является повышение тестируемости .

1 голос
/ 14 октября 2010

Я полагаю, что вы можете использовать Расширения класса EasyMock для EasyMock 2.5 или более ранней версии, и, очевидно, он включен в 3.0.См. эту часть предыдущей страницы для получения информации о том, что вы пытаетесь сделать.Тем не менее, я лично не пытался сделать это, поэтому я не знаю, насколько хорошо это будет работать.

0 голосов
/ 14 октября 2010
class ClassToTest {
    private SomethingElseInterface somethingElseDoer ;

    public ClassToTest(SomethingElseInterface somethingElseDoer) {
        this.somethingElseDoer = somethingElseDoer;
    }

    public doSomething () {
        somethingElseDoer.doSomethingElse();
    }
}

А где вы его используете:

SomethingElseInterface somethingElseDoer = ...; // in a test, this is where you mock it
ClassToTest foo = new ClassToTest(somethingElseDoer); // inject through constructor
foo.doSomething();
0 голосов
/ 14 октября 2010

Если вы хотите новый экземпляр в каждом вызове, я бы предложил рефакторинг следующим образом:

class ClassToTest {
   public doSomething () {
      SomeObject a = getInstance();
      a.doSomethingElse ();
   }
   protected SomeObject getInstance() {
      return new SomeObject();
   }
}

Затем вы можете создать тестовый класс, расширяющий ClassToTest, переопределяя метод getInstance (), с однимпоставка фиктивного объекта.

Это, конечно, жизнеспособно, только если вы в порядке с предоставлением метода getInstance (), поэтому я не рекомендую его, если класс является частью общедоступного API.Если это так, рассмотрите возможность предоставления фабричного класса, используя внедрение зависимостей.

...