Как проверить поведение параметризованного конструктора с помощью JMockit? (Новое в JMockit) - PullRequest
0 голосов
/ 20 июня 2020

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

Сначала мне нужно проверить, создается ли соответствующий класс в зависимости от заданных параметров. Во-вторых, мне нужно проверить правильность исключения в случае неверных параметров.

Для тестирования правильного класса, созданного на заводе, я могу подделать ожидаемый класс и проверить их создание. Но я не знаю, как справиться с @Tested, чтобы настроить параметры c в конструкторе.

Я не смог найти полезной подсказки ни в документации JMockit, ни при поиске inte rnet.

Ниже приведен образец класса фабрики и образец класса, созданного фабрикой (остальные похожи).

public class WorkerFactory {
    
    private Worker worker;
    
    public WorkerFactory(final String type, final String subtype) {
        
        if(type == null) throw new IllegalArgumentException("type");
        if(subtype == null) throw new IllegalArgumentException("subtype");
        
        if(type.equals("One")) {
            if(subtype.equals("A")) worker = new One_A();
            else if(subtype.equals("B")) worker = new One_B();
            else throw new IllegalArgumentException("subtype");
        }
        else if(type.equals("Two")) {
            if(subtype.equals("A")) worker = new Two_A();
            else if(subtype.equals("B")) worker = new Two_B();
            else throw new IllegalArgumentException("subtype");
        }
        else throw new IllegalArgumentException("type");
    }

    public Worker getWorker() { return worker; }
    
}



public interface Worker {
    
    public void doWork();

}



public class One_A implements Worker {

    public void doWork() {
        System.out.println(getClass().getName());
    }

}

И очень глупый скелет для требуемого теста, НО без использования JMockit.

package application;

import org.junit.Test;

public class WorkerFactoryTest {

    WorkerFactory cut;

    @Test
    public final void testWorkerFactory() {
        
        cut = new WorkerFactory("One", "A");
        cut.getWorker().doWork();
        
        cut = new WorkerFactory("One", "B");
        cut.getWorker().doWork();

        cut = new WorkerFactory("Two", "A");
        cut.getWorker().doWork();
        
        cut = new WorkerFactory("Two", "A");
        cut.getWorker().doWork();
    }

    @Test
    public final void testWorkerFactoryExceptions() {
        
        try {
            cut = new WorkerFactory("Three", "C");
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        try {
            cut = new WorkerFactory("One", "C");
        } catch (Exception e) {
            e.printStackTrace();
        }
                
    }

}

``

EDIT (2020.07.02):
The assertThrows(..) from JUnit is one way to verify exceptions. But I use still the old style try/catch variant encapsulated in functions like verifyNoException(errorMessage) with a fail(...) if i caught one or verifyXyzException(expectedExceptionMessage) with a fail(...) if I cought none. This gives me a better control over the exceptions I catch by even a good readability. A time ago i read about some drawbacks about assertThrows over the old fashin style but I can't remeber what they are.

Putting constructor logic in an init(..) method as suggested by JMockit is what I do indeed (the given example did not for simplification). But I still want to test the constructor and not the private initializer method(s). Also I prefere a design where a object gets fully initialized by constructor parameters because I don't like the (boring and ugly) setter calls. 
And verifying the parameters passed in is even a good one in my opinion.

1 Ответ

0 голосов
/ 01 июля 2020

Аннотация @Tested полезна в 90% сценариев. ios - пустой конструктор или конструкторы, где все аргументы могут быть переданы имитирующими через @Injectable. Это не тот сценарий, в котором вы находитесь из-за того, что вы пытаетесь протестировать перестановки через свой конструктор.

Кстати, JMockit подталкивает вас и говорит, что вы, возможно, захотите пересмотреть свой дизайн. Например, переместите этот конструктор logi c в метод «init (..)» (назовите его как угодно), и вы обнаружите, что с ним легче работать, и, вероятно, в целом дизайн будет лучше. Точно так же исключительные исключения из конструкторов - это плохой дизайн, от которого вас избавит init (..). Но я отвлекся ...

Ваш testWorkerFactory (..) в порядке, как есть. Нет простого способа сделать перестановку аргументов конструктора, так что все, что у вас есть, в порядке. Грубая сила - это нормально. Все не обязательно должно быть JMockit, JUnit все еще в порядке.

Для testWorkerFactoryExceptions я бы использовал assertThrows (..), поскольку он намного чище и гарантирует, что вы получите ожидаемый выброс.

...