Как к порядку вызовов метода тестирования с Moq

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

Теоретически это возможно. Я не хотел бы использовать его в производстве из-за проблем производительности, которые я ожидаю с тем интенсивным использованием lamdas/code блоков для входа.

, Но как всегда: если в сомнении, протестируйте его и измерьте влияние на загрузку ЦП и память.

28
задан Finglas 19 November 2009 в 19:50
поделиться

5 ответов

Похоже, что в настоящее время это не реализовано. См. Проблема 24: MockSequence . Эта ветка обсуждает проблему.

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

EDIT: Я не уверен, что это решает вопрос OP. Ответ Лусеро может быть более полезным.

4
ответ дан 28 November 2019 в 03:11
поделиться

Прочтите сообщение в блоге , это может решить вашу проблему.

2
ответ дан 28 November 2019 в 03:11
поделиться

В противном случае вы могли бы использовать функции обратного вызова и увеличивать / сохранять значение callIndex.

1
ответ дан 28 November 2019 в 03:11
поделиться

Недавно я создал Moq.Sequences, который предоставляет возможность проверки упорядочивания в Moq. Вы можете прочитать мой пост, в котором описано следующее:

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

Типичное использование выглядит так:

[Test]
public void Should_show_each_post_with_most_recent_first_using_sequences()
{
    var olderPost = new Post { DateTime = new DateTime(2010, 1, 1) };
    var newerPost = new Post { DateTime = new DateTime(2010, 1, 2) };
    var posts = new List<Post> { newerPost, olderPost };

    var mockView = new Mock<BlogView>();

    using (Sequence.Create())
    {
        mockView.Setup(v => v.ShowPost(newerPost)).InSequence();
        mockView.Setup(v => v.ShowPost(olderPost)).InSequence();

        new BlogPresenter(mockView.Object).Show(posts);
    }
}
31
ответ дан 28 November 2019 в 03:11
поделиться

Из исходного сообщения я мог предположить, что метод тестирования выполняет следующие вызовы операций:

var screenOne = new Screen(...);
var screenTwo = new Screen(...);
var screens = new []{screenOne, screenTwo};
var screenManager = new ScreenManager(screens);
screenManager.Draw();

Где реализация метода Draw выглядит примерно так:

public class ScreenManager
{
    public void Draw()
    {
        _screens[0].Draw();
        _screens[1].Draw();
    }
}

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

Простейшая реализация: каждый экран должен знать свой последующий элемент и вызывать свой метод Draw после рисования самого себя:

// 1st version
public class Screen(Screen screenSubSequent)
{
    private Screen _screenNext;
    public Screen(Screen screenNext)
    {
        _screenNext=screenNext;
    }
    public void Draw()
    {
        // draw himself
        if ( _screenNext!=null ) _screenNext.Draw();
    }
}

public class ScreenManager
{
    public void Draw()
    {
        _screens[0].Draw();
    }
}

static void Main()
{
    var screenOne = new Screen(null, ...);
    var screenTwo = new Screen(screenOne, ...);
    var screens = new []{screenOne, screenTwo};
    var screenManager = new ScreenManager(screens);
}

С одной стороны, каждый элемент экрана должен знать немного о другом. Это не всегда хорошо. Если это так: вы можете создать какой-нибудь класс, например ScreenDrawer. Этот объект будет хранить собственный экран и последующий экран (вероятно, унаследует его от класса Screen. Использование других миров: класс ScreenDrawer описывает структуру системы.Вот простейший сценарий реализации:

// 2nd version
public class ScreenDrawer
{
    private Screen _screenNext;
    public ScreenDrawer(Screen screenNext, ...) : base (...)
    {
        _screenNext=screenNext;
    }
    public void Draw()
    {
        // draw himself
        if ( _screenNext!=null ) _screenNext.Draw();
    }
}

public class ScreenManager
{
    public void Draw()
    {
        _screens[0].Draw();
    }
}

static void Main()
{
    var screenOne = new ScreenDrawer(null, ...);
    var screenTwo = new ScreenDrawer(screenOne, ...);
    var screens = new []{screenOne, screenTwo};
    var screenManager = new ScreenManager(screens);
}

2-й метод вводит дополнительное наследование, но не требует, чтобы класс Screen знал о своем элементе подпоследовательности.

Резюме: оба метода выполняют подпоследовательные вызовы и не требуют «последовательного» тестирования. Вместо этого они требуют проверки, вызывает ли текущий «экран» другой, и проверки, вызывает ли «ScreenManager» метод «Рисование» 1-го элемента последовательно.

Этот подход:

  1. Более тестируемый (может быть реализован с использованием большей части среды тестирования без необходимости поддержки «тестирования последовательности»);
  2. Более стабильный (никто не может легко изменить последовательность: привет потребуется не только обновить исходный код, но также обновите несколько тестов);
  3. Более объектно-ориентированный (вы работаете с объектами, а не с абстрактными сущностями, такими как «последовательность»);
  4. В результате: гораздо больше поддерживаемых.

Спасибо.

0
ответ дан 28 November 2019 в 03:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: