Издевательские методы локальных объектов области с 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); } } 
  • Как работают hashCode () и identityHashCode () на задней панели?
  • Как перебирать ключи объектов с помощью * ngFor?
  • Как обновить «массив объектов» с помощью Firestore?
  • Интервью: Можем ли мы создать абстрактный class?
  • Что такое hash-код объекта, если hashCode () не переопределяется?
  • Групповой массив объекта, вложенного в некоторые из ключей с определенными именами
  • Создание копии объекта в C #
  • Почему я могу добавить именованные свойства в массив, как если бы это был объект?
  • Заменить все объекты NSNull в NSDictionary
  • Преобразование объекта JS в массив с помощью jQuery
  • Есть ли простой способ конвертировать метку времени ISO8601 в форматированный NSDate?
  • Давайте будем гением компьютера.