Издевательские методы локальных объектов области с Mockito

Мне нужна помощь:

Пример:

void method1{ MyObject obj1=new MyObject(); obj1.method1(); } 

Я хочу, чтобы obj1.method1() в моем тесте, но чтобы быть прозрачным, поэтому я не хочу делать и изменять код. Есть ли способ сделать это в Мокито?

5 Solutions collect form web for “Издевательские методы локальных объектов области с Mockito”

Если вы действительно хотите избежать касания этого кода, вы можете использовать Powermockito (PowerMock for Mockito).

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

Ответ от @edutesoy указывает на документацию PowerMockito и упоминает конструктор, насмехающийся как подсказка, но не упоминает, как применить это к текущей проблеме в вопросе.

Вот решение, основанное на этом. Принимая код из вопроса:

 public class MyClass { void method1{ MyObject obj1=new MyObject(); obj1.method1(); } } 

Следующий тест создаст макет classа экземпляра MyObject путем подготовки classа, который его запускает (в этом примере, который я называю MyClass), с PowerMock и позволяя PowerMockito заглушить конструктор classа MyObject, а затем разрешить вам заглушить метод экземпляра MyObject1 () вызов:

 @RunWith(PowerMockRunner.class) @PrepareForTest(MyClass.class) public class MyClassTest { @Test public void testMethod1() { MyObject myObjectMock = mock(MyObject.class); when(myObjectMock.method1()).thenReturn(); PowerMockito.whenNew(MyObject.class).withNoArguments().thenReturn(myObjectMock); MyClass objectTested = new MyClass(); objectTested.method1(); ... // your assertions or verification here } } 

При этом ваш внутренний вызов method1 () вернет вам то, что вы хотите.

Если вам нравятся однострочные символы, вы можете сделать код короче, создав макет и встроенную строку:

 MyObject myObjectMock = when(mock(MyObject.class).method1()).thenReturn().getMock(); 

Ни за что. Вам понадобится инъекция зависимостей, то есть вместо того, чтобы создать экземпляр obj1, он должен быть предоставлен какой-либо фабрикой.

 MyObjectFactory factory; public void setMyObjectFactory(MyObjectFactory factory) { this.factory = factory; } void method1() { MyObject obj1 = factory.get(); obj1.method(); } 

Тогда ваш тест будет выглядеть так:

 @Test public void testMethod1() throws Exception { MyObjectFactory factory = Mockito.mock(MyObjectFactory.class); MyObject obj1 = Mockito.mock(MyObject.class); Mockito.when(factory.get()).thenReturn(obj1); // mock the method() Mockito.when(obj1.method()).thenReturn(Boolean.FALSE); SomeObject someObject = new SomeObject(); someObject.setMyObjectFactory(factory); someObject.method1(); // do some assertions } 

Вы можете сделать это, создав фабричный метод в MyObject:

 class MyObject { public static MyObject create() { return new MyObject(); } } 

затем издеваться над этим с PowerMock .

Однако, издеваясь над методами локального объекта scope, вы зависите от того, что часть реализации метода остается неизменной. Таким образом, вы теряете способность реорганизовать эту часть метода без нарушения теста. Кроме того, если вы обманываете возвращаемые значения в макете, тогда ваш тестовый пакет может пройти, но метод может вести себя неожиданно при использовании реального объекта.

В общем, вы, вероятно, не должны пытаться это сделать. Скорее, позволяя тест-драйву вашего кода (ака TDD), вы бы пришли к решению вроде:

 void method1(MyObject obj1) { obj1.method1(); } 

проходящей в зависимости, которую вы можете легко высмеять для модульного теста.

Лучшим подходом является не касаться кода и издеваться над конструктором, как в этом примере, для издевательств над созданием объекта File внутри метода. Не забудьте поставить class, который будет создавать файл в @PrepareForTest.

 package hello.easymock.constructor; import java.io.File; import org.easymock.EasyMock; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.api.easymock.PowerMock; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @RunWith(PowerMockRunner.class) @PrepareForTest({File.class}) public class ConstructorExampleTest { @Test public void testMockFile() throws Exception { // first, create a mock for File final File fileMock = EasyMock.createMock(File.class); EasyMock.expect(fileMock.getAbsolutePath()).andReturn("/my/fake/file/path"); EasyMock.replay(fileMock); // then return the mocked object if the constructor is invoked Class< ?>[] parameterTypes = new Class[] { String.class }; PowerMock.expectNew(File.class, parameterTypes , EasyMock.isA(String.class)).andReturn(fileMock); PowerMock.replay(File.class); // try constructing a real File and check if the mock kicked in final String mockedFilePath = new File("/real/path/for/file").getAbsolutePath(); Assert.assertEquals("/my/fake/file/path", mockedFilePath); } } 
  • Что такое hash-код объекта, если hashCode () не переопределяется?
  • Разница между объектом и classом в Scala
  • Как вызвать метод Objective C из Javascript и отправить данные в Javascript в iOS?
  • Имя свойства объекта как число
  • Что такое classы, ссылки и объекты?
  • Статические и нестатические члены classа
  • Все в .NET является объектом?
  • Преобразование объекта JS в массив с помощью jQuery
  • Не удается скрыть строку состояния в iOS7
  • Как сохранить пользовательский ArrayList на экране Android?
  • Как работают hashCode () и identityHashCode () на задней панели?
  • Давайте будем гением компьютера.