Есть ли лучший способ проверить этот метод? - PullRequest
1 голос
/ 21 марта 2012

Я хотел бы запустить некоторые модульные тесты по методу, приведенному ниже. Я передаю имитированный интерфейс ( vehicleObject ) в ProcessVehicles , но как только он пройден, он переназначается DetermineVehicleType , поэтому мой смоделированный объект бесполезен.Моей первой идеей было бы создать логическое значение, чтобы определить, следует ли запускать DetermineVehicleType , и добавить его в качестве параметра, но это звучит очень грязно.Есть ли лучший способ обойти это?

Метод с добавлением ложного объекта:

public void ProcessVehicles(ICarObject CarObject)
{
    IObject vehicleObject = DetermineVehicleType(carObject);
    vehicleObject.ProcessVehicle(carObject);
}

Оригинальный код:

public void ProcessVehicles()
{
    IObject vehicleObject = DetermineVehicleType(carObject);
    vehicleObject.ProcessVehicle(carObject);
}

Примечание: я не могуперед вызовом DetermineVehicleType проверьте, имеет ли значение VehicleObject значение null, поскольку оно может быть не равно нулю, когда класс фактически используется.В долгосрочной перспективе, возможно, тотальный рефакторинг - это ответ, на данный момент это не тот ответ, который я ищу, может быть, нет другого варианта.

метод DetermineVehicleType является приватным

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

Ответы [ 2 ]

3 голосов
/ 21 марта 2012

Какой модификатор доступа есть у DetermineVehicleType?Вы можете заглушить этот метод, чтобы он возвращал ваш смоделированный интерфейс (Рой Ошеров называет это abstract test driver pattern, я полагаю).В противном случае это выглядит как основной кандидат на рефакторинг:)

Для рефакторинга вашего кода вы должны сделать что-то вроде этого

Сначала измените сигнатуру метода

protected virtual IObject DetermineVehicleType(CarObject obj)
{
    //Do whatever you normally do
}

Затемв своем тесте вы можете создать заглушку из указанного выше класса и вернуть ей заглушенный объект IObject независимо от того, передан ли CarObject. Вы можете либо вручную создать класс заглушки, унаследовав от класса, либо использоватьчто-то вроде MOQ для достижения этой цели.Дайте мне знать, если вам нужно, чтобы я подробнее остановился на этом.

Однако еще одно замечание:

Лучший способ реорганизовать это - просто передать IObject вProcessVehicles, как видно из этого примера, здесь у вас есть нарушение SRP , где метод ProcessVehicles делает больше, чем обрабатывает их.Но, возможно, именно из этого упрощенного примера

ПОЛНОЕ Обновление реализации

    [Test]
    public void TestMethod()
    {
        var testerStub = new TesterStub();
        testerStub.ProcessVehicles();
        //Assert something here
    }

    public class TesterStub : Tester
    {
        public override IObject DetermineVehicleType(CarObject obj)
        {
            var mockObject = new Mock<IObject>();
            mockObject.Setup(x => x.SomeMethod).Returns(Something);
            return mockObject.Object;
        }
    }

    public class Tester
    {
        protected virtual IObject DetermineVehicleType(CarObject obj)
        {
            return new ObjectTester();
        }

        public void ProcessVehicles()
        {
            var carType = DetermineVehicleType(new CarObject());

        }
    }

    public class ObjectTester : IObject
    {
    }

    public interface IObject
    {
    }

    public class CarObject
    {
    }
1 голос
/ 21 марта 2012

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

Учтите это: метод ProcessVehicles вызывает метод в экземпляре с именем DetermineVehicleType.Что делает ваш класс?Это Process Vehicles или Determine Vehicle Type?Это для меня указывает на нарушение ПСП, если вы воспринимаете это буквально.Ваш класс пытается выполнить более одной работы.

Возможно, это означает, что SRP не одобряет частные вспомогательные методы.Некоторые комментаторы действительно считают, что это так.Я не уверен, что я делаю;как всегда, здравый смысл является ключевым.

Если бы я реорганизовал этот код, я бы дал классу что-то вроде IVehicleCategoryHelper, который выставляет DetermineVehicleType.Возможно, это будет передано через его конструктор, или если мы реализуем полное Fat Dependency Injection, IFactory, чтобы экземпляр мог получить IVehicleCategoryHelper, когда он ему нужен, в зависимости от контекста.

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

...