Тестирование многопоточных сервисных методов в макетах - PullRequest
2 голосов
/ 30 августа 2011

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

[Test]
public void CanSaveCustomersInParallel()
{
    var customers = new List<List<Customer>>
                        {
                            new List<Customer>
                                {
                                    new Customer {FirstName = "FirstName1"},
                                    new Customer {FirstName = "FirstName2"}
                                },
                            new List<Customer>
                                {
                                    new Customer {FirstName = "FirstName3"},
                                    new Customer {FirstName = "FirstName4"}
                                }
                        };
    _serviceCustomers.ParallelSaveBatch(customers);
    _repoCustomers
        .Verify(x => x.SaveBatch(It.IsAny<List<Customer>>()), Times.Exactly(2));
}

Конечно, этот тест иногда дает сбой, а иногда и нет.Но это неверно по своей сути.Можете ли вы посоветовать мне, как переписать это?

Ответы [ 3 ]

4 голосов
/ 18 октября 2011

Ну, следующая заглушка сделала свое дело:

internal class ServiceStub: Service<DummyEntity>
{
    private int _count;

    public int Count
    {
        get { return _count; }
    }

    public override void SaveBatch(IEnumerable<object> entities)
    {
       lock(this)
       {
           _count++;
       }
    }

    public ServiceStub(IRepository<DummyEntity> repository):base(repository)
    {
        _count = 0;
    }
}

И юнит-тест выглядит следующим образом:

    [Test]
    public void CanSaveCustomersInParallel()
    {
        var service = new ServiceStub(new DummyRepository());
        var customers = new List<List<Customer>>
                            {
                                new List<Customer>
                                    {
                                        new Customer {FirstName = "FirstName1"},
                                        new Customer {FirstName = "FirstName2"}
                                    },
                                new List<Customer>
                                    {
                                        new Customer {FirstName = "FirstName3"},
                                        new Customer {FirstName = "FirstName4"}
                                    }
                            };
        service.ParallelSaveBatch(customers);
        Assert.AreEqual(service.Count, customers.Count);
    }
4 голосов
/ 12 сентября 2013

Возможно, вам будет интересно узнать, что по состоянию на v 4.1 Moq теперь имеет значительно улучшенную безопасность потоков, и вы должны найти такие тесты, как ваш, при параллельной работе теперь должны проверятькак и ожидалось.

Подробнее о нестабильном поведении Moq здесь

Типичные проблемы, встречающиеся в версиях <= 4.0, включали случайные <code>NullReferenceException или IndexOutOfRangeException, иmock.Verify(<>, Times.Exactly(N)) не удалось (обычно с недостаточным количеством).Начиная с 4.1, эти проблемы теперь кажутся исправленными MacGyvered , ~ благодаря сообществу!

Редактировать Согласно @ комментарию Дэнни нижеобратите внимание, что изменения, внесенные в 4.1, включали блокировку Mock , которая не очень полезна, если вам нужно проверить параллельность вашего кода.

0 голосов
/ 04 сентября 2011

Изменение конструкции может упростить этот тест. Создайте SaveWorker, который выполняет реальную работу, и прокси, который выполняет работу SaveWork в другом потоке (та же абстракция). Затем SaveWorkerFactory, который возвращает ThreadedSaveWorker, предоставленный клиенту. Наконец, вставьте макет SaveWorkerFactory в _serviceCustomers и убедитесь, что он выполняет 2 вызова.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...