Mockito - конструктор насмешливых классов - PullRequest
8 голосов
/ 09 июня 2011

Я пишу JUnit для класса, который ссылается на унаследованный класс через конструктор.Устаревший класс находится в сторонней фляге, поэтому я не могу изменить его, чтобы упростить жизнь ....

Этот класс тестируется ...

public MyClass {

    public String methodToTest(String param) {
        LegacyClass legacy = new LegacyClass(param);
        *..... etc ........*
    }
}

Этоэто то, что я пытаюсь сделать в мокито JUnit.

public MyClassTest {

    @Test
    public void testMethodToTest() throws Exception {
        LegacyClass legacyMock = mock(LegacyClass.class);
        when(*the LegacyClass constructor with param is called*).thenReturn(legacyMock);
        *.... etc.....*
    }
}

Любые идеи о том, как я могу это сделать ?????

Ответы [ 3 ]

8 голосов
/ 13 июня 2011

Сделать строителем для LegacyClass:

public class LegacyClassBuilder {

    public LegacyClass build(String param) {
        return new LegacyClass(param);
    }

}

Таким образом, ваш класс может быть протестирован, поэтому он создает LegacyClass с правильным параметром.

public MyClass {

    private LegacyClassBuilder builder;

    public setBuilder(LegacyClassBuilder builder) {
        this.builder = builder;
    }

    public String methodToTest(String param) {
        LegacyClass legacy = this.builder.build(param);
        ... etc
    }
}

Тест будет выглядеть примерно так:

// ARRANGE
LegacyClassBuilder mockBuilder = mock(LegacyClassBuilder.class);
LegacyClass mockLegacy = mock(LegacyClass.class); 
when(mockBuilder.build(anyString()).thenReturn(mockLegacy);

MyClass sut = new MyClass();
sut.setBuilder(mockBuilder);
String expectedParam = "LOLCAT";


// ACT
sut.methodToTest(expectedParam);

// ASSERT
verify(mockBuilder).build(expectedParam);

Если LegacyClass окажется final, то вам нужно создать не финальную оболочку для LegacyClass, которую будет использовать MyClass.

5 голосов
/ 04 сентября 2012

Вы можете использовать PowerMockito Framework:

import static org.powermock.api.mockito.PowerMockito.*;

whenNew(LegacyClass.class)
  .withParameterTypes(String.class)
  .withArguments(Matchers.any(String.class))
  .thenReturn(new MockedLegacyClass(param));

Затем напишите вашу реализацию MockedLegacyClass в соответствии с вашими требованиями к тестированию.

0 голосов
/ 06 марта 2018

Я считаю, что нельзя издеваться над конструкторами с помощью Mockito. Вместо этого я предложу следующий подход:

  public MyClass {

    public String methodToTest(String param) {
     if(legacy== null){
      //when junit runs, you will get mocked object (not null), hence don't initialize 
        LegacyClass legacy = new LegacyClass(param);
      }
        *..... etc ........*
    }
}

public MyClassTest {

@InjectMock
Myclass myclass; // inject mock the real testable class
@Mock
LegacyClass legacy

@Test
public void testMethodToTest() throws Exception {    
    // when(legacy-constructor).thenReturn() ---not Required
    // instead directly mock the required methods using mocked legacy object
    when(legacy.getSomething(Mockito.any(String.class))).thenReturn(null);
        *.... etc.....*
    }
}
...