Mockito: как проверить, что конструктор был вызван?

Я использую Mockito для тестирования методов в моем приложении Java.

Как я могу проверить, что конструктор вызывается один раз?

Я пытаюсь сделать проверку, похожую на эту:

verify(myClass, times(1)).doSomething(anotherObject);

но я не могу проверить, что конструктор был вызван, поскольку у него нет метода, подобного, например,doSomething().

6 ответов


Это невозможно сделать с помощью Mockito, так как создаваемый объект не является издевательским объектом. Это также означает, что вы не сможете ничего проверить на новый объект.

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

ли вы счастливы изменять вашу конструкцию для того чтобы одеть ваши испытания до вас!


вы можете сделать это с Mockito и PowerMockito.

скажем, у вас есть ClassUnderTest с конструктором

public class ClassUnderTest {
    String name;
    boolean condition;

    public ClassUnderTest(String name, boolean condition) {
       this.name = name;
       this.condition = condition;
       init();
    }

    ...
}

и другой класс, который вызывает этот конструктор

public class MyClass {

    public MyClass() { } 

    public void createCUTInstance() {
       // ...
       ClassUnderTest cut = new ClassUnderTest("abc", true);
       // ...
    }

    ...
}

в тестовом классе мы могли бы...

(1) Используйте PowerMockRunner и приведите оба целевых класса выше в аннотации PrepareForTest:

@RunWith(PowerMockRunner.class)
@PrepareForTest({ ClassUnderTest.class, MyClass.class })
public class TestClass {

(2) перехватите конструктор, чтобы вернуть макет объекта:

@Before
public void setup() {
    ClassUnderTest cutMock = Mockito.mock(ClassUnderTest.class);
    PowerMockito.whenNew(ClassUnderTest.class)
                .withArguments(Matchers.anyString(), Matchers.anyBoolean())
                .thenReturn(cutMock);
}

(3) Проверка конструктора звоните:

@Test
public void testMethod() {
    // prepare
    MyClasss myClass = new MyClass();

    // execute
    myClass.createCUTInstance();

    // checks if the constructor has been called once and with the expected argument values:
    String name = "abc";
    String condition = true;
    PowerMockito.verifyNew(ClassUnderTest.class).withArguments(name, condition);
}

verify() метод ожидает насмешливый объект (уже созданный объект). И constructor не может быть вызван на created object.


Это невозможно с Mockito и звучит как плохой дизайн.

вы можете использовать фабрику и передать ее тестируемому объекту. После этого вы можете легко издеваться над фабрикой и проверить, был ли вызван ее метод create.

непосредственно создавая объекты в коде, вы создаете жесткую зависимость от конкретных реализаций, что делает код более сложным, а иногда и невозможным для модульного тестирования. Это решается с помощью инъекции зависимостей (DI) и инверсии Контроль (МОК).


конструктор не возвращает объект, если он не... и если это не удастся, программа, скорее всего, рухнет.

жесткий я полагаю, что это сделает это:

Object obj = null;

obj = new Object();

if (obj == null) {
  //... Didn't Work
} else {
  //... Worked
}

вы не сможете издеваться над конструктором с помощью mockito, но с помощью powermockito вы сможете это проверить. Настройка будет что-то вроде этого

public class MyClass{

   public MyClass(String name){}

   public void doSomethingUseFul(){
      //.......
   }

}

public class Helper {

   public void goHelp(){
       new MyClass("apple").doSomethingUseFul();
   } 

}

/ / Mock

    @RunWith(PowerMockRunner.class)
    @PrepareForTest(MyClass.class)
    public class MockMyClass {
    @InjectMocks
    private Helper helper;

        @Test
        public void testDoSomethingUseFul() {
             MyClass  c = mock(MyClass.class); 
             doNothing().when(c).doSomethingUseFul();
             PowerMockito.whenNew(MyClass. class).withArguments(anyString()).thenReturn(c);
             helper.goHelp(); 
             verifyNew(MyClass.class).withArguments(anyString())


        }
    }