У меня есть фабричный класс, конструктор которого принимает два параметра. В зависимости от этих параметров фабрика создает четыре разных типа классов или выдает исключения 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.