Как использовать макеты в этом случае? - PullRequest
1 голос
/ 31 марта 2011

Вот моя проблема:

У меня есть n-уровневое приложение, для которого я должен написать модульные тесты. Модульные тесты предназначены для бизнес-уровня.

У меня есть метод для проверки, который называется Insert(), и этот использует два защищенных метода от наследования и напрямую вызывает метод из уровня доступа к данным.

Итак, я сделал фиктивный объект для DAL. Но вот в чем дело, в (edit :) защищенном методе от наследования, он будет использовать другой объект из DAL! Кажется, над этим издеваться невозможно!

Вот метод для тестового кода:

public int Insert(MYOBJECT aMyObject)
    {
            //first inherited method use the FIRSTDALOBJECT so the mock object --> No problem
            aMyObject.SomeField= FirstInherited();

            //Second inherited method (see after) --> my problem
            aMyObject.SomeOtherField = SecondInherited();

            // Direct access to DALMethod, use FIRSTDALOBJECT so the mock -->No Problem
            return this.FIRSTDALOBJECT.Insert(aMyObject);             
     }

Вот метод SecondInherited:

 protected string SecondInherited ()
    { 
        // Here is my problem, the mock here seems not be possible for seconddalobject                                          
        return ( new SECONDDALOBJECT Sdo().Stuff());
    }

А вот код метода модульного тестирования:

    [TestMethod()]
    public void InsertTest()
    {
        BLLCLASS_Accessor target = new BLLCLASS_Accessor();
        MYOBJECT aMyObject = new MYOBJECT { SomeField = null, SomeOtherField = 1 };
        int expected = 1;
        int actual;

        //mock
        var Mock = new Mock<DAL.INTERFACES.IFIRSTDALOBJECT>();
        //Rec for calls
        List<SOMECLASS> retour = new List<SOMECLASS>();
        retour.Add(new SOMECLASS());

        //Here is the second call (last from method to test)
        Mock
            .Setup(p => p.Insert(aMyObject))
            .Returns(1);

        // Here is the first call (from the FirstInherited())
        Mock
            .Setup(p => p.GetLast())
            .Returns(50);
        // Replace the real by the mock
        target.demande_provider = Mock.Object;

        actual = target.Insert(aMyObject);
        Assert.AreEqual(/*Some assertion stuff*/);
    }

Спасибо, что прочитали все вопросы :-) Надеюсь, это достаточно понятно.

Ответы [ 2 ]

3 голосов
/ 31 марта 2011

В вашем тексте написано, что SecondInherited равно private, а в примере кода это protected. В любом случае, если это не protected, я бы предложил изменить его квалификатор доступа в качестве первого шага.

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

Таким образом, вы можете написать свой первый модульный тест (ы) с минимальными изменениями в тестируемом классе, таким образом сводя к минимуму шансы что-то сломать . После того, как у вас есть модульные тесты, они позволят вам сделать больше рефакторинга безопасно, в конечном итоге достигнув лучшего (более проверяемого / насмешливого) дизайна, такого как Dependency Injection или Factory. (Я бы, вероятно, предпочел бы Abstract Factory вместо Factory Method здесь, поскольку последний практически заставит вас продолжать создавать подклассы тестируемого класса).

Основная, очень рекомендуемая книга для изучения этой техники (и многих других): Эффективная работа с устаревшим кодом .

2 голосов
/ 31 марта 2011

Нет шансов посмеяться над этим с MOQ.У вас есть два варианта:

  1. Используйте TypeMock или Moles, чтобы высмеивать SECONDDALOBJECT class
  2. Рефакторинг кода, поэтому экземпляр SECONDDALOBJECT создается не так, как онесть, но способом, который может быть подделан (фабричный метод, DI, ...) (предпочтительно!)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...