Проверка результатов Фабрики в модульном тесте - PullRequest
16 голосов
/ 01 сентября 2008

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

Я хотел бы знать ответ на Java, но если есть решение, которое пересекает языки, я хотел бы знать его.

Номер 2. в ответе будет сделано как и другой ответ? Если это так, я отмечу другой принятый ответ и перефразирую свой вопрос, чтобы адресовать как фабрику, где возвращается интерфейс, и вы не знаете, какой тип конкретного класса реализовал интерфейс, так и случай, когда вы знаете, какой конкретный класс б.

Ответы [ 5 ]

25 голосов
/ 10 декабря 2015

То, что вы пытаетесь сделать, это не модульное тестирование

Если вы проверяете, являются ли возвращаемые объекты экземплярами определенных конкретных классов, вы не тестируете модули. Вы тестирование интеграции. Хотя интеграционное тестирование важно, это не одно и то же.

В модульном тестировании вам нужно только протестировать сам объект. Если вы утверждаете конкретный тип возвращаемых абстрактных объектов, вы проверяете реализацию возвращаемого объекта.

Юнит-тестирование на объектах в целом

При модульном тестировании нужно утверждать четыре вещи:

  1. Возвращаемые значения запросов (не пустые методы) - это то, что вы ожидаете от них.
  2. Побочные эффекты команд (методы void) изменяют сам объект так, как вы ожидаете.
  3. Получены команды, отправленные другим объектам (обычно это делается с помощью насмешек).

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

Фабрики модульных испытаний

Модульное тестирование на фабриках действительно неинтересно, потому что вас не интересует поведение возвращаемых объектов запросов . Такое поведение (мы надеемся) проверено везде, вероятно, при модульном тестировании самого объекта. Вас действительно действительно интересует, имеет ли возвращаемый объект правильный тип , что гарантируется, если ваша программа компилируется.

Поскольку фабрики не меняются с течением времени (потому что тогда они будут "строителями", что является другим шаблоном), нет команд для тестирования.

Фабрики отвечают за создание экземпляров объектов, поэтому они не должны зависеть от других фабрик, которые делают это для них. Они могут зависеть от Строителя, но даже в этом случае мы не должны проверять правильность Строителя, только независимо от того, получит ли Строитель сообщение.

Это означает, что все, что вам нужно проверить на фабриках, - отправлять ли они сообщения объектам, от которых они зависят. Если вы используете Dependency Injection, это почти тривиально. Просто смоделируйте зависимости в ваших модульных тестах и ​​убедитесь, что они получают сообщения.

Сводка заводов по модульному тестированию

  1. Не проверяйте ни поведение, ни детали реализации возвращаемых объектов! Ваша фабрика не несет ответственности за реализацию экземпляров объекта!
  2. Проверьте, получены ли команды, отправленные зависимостям.

Вот и все. Если нет никаких зависимостей, тестировать нечего. За исключением, может быть, утверждения, что возвращаемый объект не является ссылкой null.

Фабрики интеграционных испытаний

Если у вас есть требование, чтобы возвращаемый тип абстрактного объекта был экземпляром определенного конкретного типа, то это подпадает под интеграционное тестирование.

Другие здесь уже ответили, как это сделать с помощью оператора instanceof.

18 голосов
/ 01 сентября 2008

Так как я не знаю, как выглядит ваш фабричный метод, все, что я могу посоветовать сейчас, это

  1. Убедитесь, что объект является правильной конкретной реализацией, которую вы искали:

    IMyInterface fromFactory = factory.create(...);  
    Assert.assertTrue(fromFactory instanceof MyInterfaceImpl1);
    
  2. Вы можете проверить, настроены ли на заводе конкретные экземпляры с действительными переменными экземпляра.

0 голосов
/ 13 августа 2018

Если ваша фабрика возвращает конкретный экземпляр, вы можете использовать аннотацию @ Parameters , чтобы получить более гибкий автоматический модульный тест.

package it.sorintlab.pxrm.proposition.model.factory.task;

import org.junit.Test;

import java.util.Arrays;
import java.util.Collection;

import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

import static org.junit.Assert.*;

@RunWith(Parameterized.class)
public class TaskFactoryTest {

    @Parameters
    public static Collection<Object[]> data() {
        return Arrays.asList(new Object[][] {
                { "sas:wp|repe" , WorkPackageAvailabilityFactory.class},
                { "sas:wp|people", WorkPackagePeopleFactory.class},
                { "edu:wp|course", WorkPackageCourseFactory.class},
                { "edu:wp|module", WorkPackageModuleFactory.class},
                { "else", AttachmentTaskDetailFactory.class}
        });
    }

    private String fInput;
    private Class<? extends TaskFactory> fExpected;

    public TaskFactoryTest(String input, Class<? extends TaskFactory> expected) {
        this.fInput = input;
        this.fExpected = expected;
    }

    @Test
    public void getFactory() {
        assertEquals(fExpected, TaskFactory.getFactory(fInput).getClass());
    }
}

Этот пример сделан с использованием Junit4 . Вы можете заметить, что только с одной строкой кода вы можете проверить все результаты вашего метода Factory.

0 голосов
/ 02 сентября 2008

@ cem-catikkas Я думаю, было бы правильнее сравнивать значения getClass (). GetName (). В случае, когда класс MyInterfaceImpl1 находится в подклассе, ваш тест может быть нарушен, поскольку подкласс является экземпляром MyInterfaceImpl1. Я бы переписал так:

IMyInterface fromFactory = factory.create(...);  
Assert.assertEquals(fromFactory.getClass().getName(), MyInterfaceImpl1.class.getName());

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

0 голосов
/ 01 сентября 2008
if (myNewObject instanceof CorrectClass)
{
    /* pass test */
}

обновление:

Не знаю, почему это было отмечено, поэтому я немного расширю ...

public void doTest()
{
    MyInterface inst = MyFactory.createAppropriateObject();
    if (! inst instanceof ExpectedConcreteClass)
    {
        /* FAIL */
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...