Макет конструктора с параметром
у меня есть класс, как показано ниже:
public class A {
public A(String test) {
bla bla bla
}
public String check() {
bla bla bla
}
}
логика в конструкторе A(String test) и check() это то, что я пытаюсь высмеять. Я хочу любые звонки, как:new A($$$any string$$$).check() возвращает пустой строкой "test".
пробовал:
A a = mock(A.class);
when(a.check()).thenReturn("test");
String test = a.check(); // to this point, everything works. test shows as "tests"
whenNew(A.class).withArguments(Matchers.anyString()).thenReturn(rk);
// also tried:
//whenNew(A.class).withParameterTypes(String.class).withArguments(Matchers.anyString()).thenReturn(rk);
new A("random string").check(); // this doesn't work
но это, кажется, не работает. new A($$$any string$$$).check() по-прежнему проходит через логику конструктора вместо извлечения издевательского объекта A.
4 ответов:
код, который вы опубликовали, работает для меня с последней версией Mockito и Powermockito. Может быть, вы еще не подготовили? Попробуйте это:
A.java
public class A { private final String test; public A(String test) { this.test = test; } public String check() { return "checked " + this.test; } }Моцка.java
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @RunWith(PowerMockRunner.class) @PrepareForTest(A.class) public class MockA { @Test public void test_not_mocked() throws Throwable { assertThat(new A("random string").check(), equalTo("checked random string")); } @Test public void test_mocked() throws Throwable { A a = mock(A.class); when(a.check()).thenReturn("test"); PowerMockito.whenNew(A.class).withArguments(Mockito.anyString()).thenReturn(a); assertThat(new A("random string").check(), equalTo("test")); } }оба теста должны пройти с mockito 1.9.0, powermockito 1.4.12 и junit 4.8.2
насколько мне известно, вы не можете издеваться над конструкторами с помощью mockito, только методы. Но согласно wiki на кодовой странице Mockito google есть способ издеваться над поведением конструктора, создавая метод в вашем классе, который возвращает новый экземпляр этого класса. тогда вы можете издеваться над этим методом. Ниже находится отрывок непосредственно из Mockito wiki:
Pattern 1-Использование однострочных методов для создания объектов
To используйте шаблон 1 (тестирование класса под названием MyClass), вы бы заменить вызов, как
Foo foo = new Foo( a, b, c );С
Foo foo = makeFoo( a, b, c );и написать однострочный метод
Foo makeFoo( A a, B b, C c ) { return new Foo( a, b, c ); }важно, что вы не включаете никакой логики в метод; только одна строка, которая создает объект. Причина этого в том, что сам метод никогда не собирается быть испытанным блоком.
когда вы приходите, чтобы проверить класс, объект, который вы тестируете будет на самом деле Mockito spy, с этим методом переопределен, чтобы вернуть a издеваться. То, что вы тестируете не сам класс, а очень немного измененная версия его.
ваш тестовый класс может содержать такие элементы, как
@Mock private Foo mockFoo; private MyClass toTest = spy(new MyClass());наконец, внутри вашего метода тестирования вы издеваетесь над вызовом makeFoo с линией, как
doReturn( mockFoo ) .when( toTest ) .makeFoo( any( A.class ), any( B.class ), any( C.class ));вы можете использовать вычислителей, которые являются более конкретными, чем любой() если вы хотите проверьте аргументы, которые передаются в конструктор.
если вы просто хотите вернуть издевательский объект вашего класса, я думаю, что это должно работать для вас. В любом случае вы можете прочитать больше о создании насмешливого объекта здесь:
Без Использования Powermock .... См. пример ниже, основанный на ответе Бена Глассера, так как мне потребовалось некоторое время, чтобы понять это ..надеюсь, что это экономит несколько раз ...
Исходный Класс :
public class AClazz { public void updateObject(CClazz cClazzObj) { log.debug("Bundler set."); cClazzObj.setBundler(new BClazz(cClazzObj, 10)); } }Модифицированных Класс :
@Slf4j public class AClazz { public void updateObject(CClazz cClazzObj) { log.debug("Bundler set."); cClazzObj.setBundler(getBObject(cClazzObj, 10)); } protected BClazz getBObject(CClazz cClazzObj, int i) { return new BClazz(cClazzObj, 10); } }Тест Класс
public class AClazzTest { @InjectMocks @Spy private AClazz aClazzObj; @Mock private CClazz cClazzObj; @Mock private BClazz bClassObj; @Before public void setUp() throws Exception { Mockito.doReturn(bClassObj) .when(aClazzObj) .getBObject(Mockito.eq(cClazzObj), Mockito.anyInt()); } @Test public void testConfigStrategy() { aClazzObj.updateObject(cClazzObj); Mockito.verify(cClazzObj, Mockito.times(1)).setBundler(bClassObj); } }
Mockito имеет ограничения тестирования окончательных, статических и частных методов.
с библиотекой тестирования jMockit, вы можете сделать несколько вещей, очень легко и прямо вперед, как показано ниже:
макет конструктора класса java. io. File:
new MockUp<File>(){ @Mock public void $init(String pathname){ System.out.println(pathname); // or do whatever you want } };
- имя открытого конструктора должно быть заменено на $init
- Аргументы и исключения, брошенные остается тем же
- тип возврата должен быть определен как void
Mock a статический метод:
- удалить статику из метода mock signature
- подпись метода остается такой же в противном случае
Comments