JMockit — как внедрить абстрактный метод

Я пытаюсь написать модульный тест для класса, который расширяет абстрактный класс, но тесты все еще пытаются вызывать настоящие абстрактные методы. Есть ли способ внедрить абстрактный класс Mocked и проверить, был ли вызван абстрактный метод?

Тест

public class TestThisClassTest {
    @Tested
    TestThisClass testThisClass;

    @Injectable
    String names;
    @Injectable
    String username;
    @Injectable
    char[] password = {'t', 'e', 's', 't', 's'};;
    @Injectable
    String destinationName;

    @Injectable
    AbstractClass abstractClass; // Thought this would inject but it's not

    @Test(description = "Verify that sendMessageAbstractMethod is called")
    public void testSendMessage(@Mocked ObjectMessage message) throws Exception {

        testThisClass.sendMessage(message); // This is instantiating AbstractClass when it shouldn't be
        new Verifications(){{
            abstractClass.sendMessageAbstractMethod((Object) any);
            times = 1;
        }};
    }
}

TestThisClass.class

public class TestThisClass extends AbstractClass {

    public TestThisClass() {
        super();
    }

    @Inject
    public TestThisClass(String names, String username, char[] password, String destinationName) {
        super(names, username, password, destinationName);
    }

    public void sendMessage(Object message) throws Exception {  // Trying to test this method
        sendMessageAbstractMethod(message);  // This is "doing stuff." Need it verify this is called and move on
     
    }
}

Абстрактный класс

public abstract class AbstractClass {
    public AbstractClass(String names, String username, char[] password, String destinationName) {
        this.names = names;
        this.username = username;
        this.password = password;
        this.destinationName = destinationName;
    }


    protected void sendMessageAbstractMethod(Object message) throws Exception {
        //do stuff
    }
}

person PT_C    schedule 16.11.2020    source источник
comment
Почему вы пытаетесь внедрить абстрактный класс? По определению у вас не может быть объекта абстрактного класса, у вас могут быть только экземпляры неабстрактных классов.   -  person Progman    schedule 16.11.2020
comment
@Progman Я пытаюсь внедрить Mocked-версию абстрактного класса, чтобы я мог записать вызов абстрактного метода. Есть ли способ сделать это без создания экземпляра абстрактного класса?   -  person PT_C    schedule 16.11.2020


Ответы (2)


Решил это с помощью шпиона

public class TestThisClassTest {

    @Injectable
    String names;
    @Injectable
    String username;
    @Injectable
    char[] password = {'t', 'e', 's', 't', 's'};;
    @Injectable
    String destinationName;

    @Test
    public void testSendMessage(@Mocked ObjectMessage message) throws Exception {
        TestThisClass abstractImpl = spy(new TestThisClass());
        doNothing().when(abstractImpl).sendMessageAbstractMethod(any());

        abstractImpl.sendMessage(message));
        new Verifications(){{
            verify(abstractImpl, times(1)).sendMessage(any());
        }};
    }
}
person PT_C    schedule 16.11.2020

Это должно работать:

public class TestThisClassTest {
@Tested
TestThisClass testThisClass;

@Injectable
String names;
@Injectable
String username;
@Injectable
char[] password = {'t', 'e', 's', 't', 's'};;
@Injectable
String destinationName;

@Test(description = "Verify that sendMessageAbstractMethod is called")
public void testSendMessage(@Mocked ObjectMessage message) throws Exception {

    testThisClass.sendMessage(message); 

    new Verifications(testThisClass){{
        testThisClass.sendMessageAbstractMethod((Object) any);
        times = 1;
    }};
}

}

person Jeff Bennett    schedule 06.12.2020