Как передать аргументы на уровень доступа к данным, который использует System.Action в качестве входного параметра?

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

Тестируемый метод вызывает метод Create класса DataService.

Вызов метода создания

var contactProductLink = this.dsService.Create<ContactProductLink>(x =>
{
    x.ContactRoleId = prod.RoleId;
    x.ContactId = contactViewModel.ContactId;
    x.ProductId = prod.ProductId;
    x.Active = true;
    x.InsertDate = DateTime.Now;
    x.InsertUserId = user.employeeId;
    x.UpdateDate = DateTime.Now;
    x.UpdateUserId = user.employeeId;
});

Метод создания DataService:

public TEntity Create<TEntity>(Action<TEntity> propertySetter = null) where TEntity : class
{
    var tEntity = this.Context.Create<TEntity>();
    if (propertySetter != null)
    {
        propertySetter(tEntity);
    }

    return tEntity;
}

Подход, который я выбрал (и, возможно, есть лучший способ), заключается в использовании NSubstitute для имитации DataService. Когда я делаю свои утверждения в конце, я проверяю, был ли вызван метод Create:

mockDataSupplierService.Received().Create<ContactProductLink>(Arg.Any<Action<ContactProductLink>>());

Однако я хотел бы также проверить правильность ввода, отправленного методу, и здесь у меня возникают проблемы. Я могу получить объект System.Action, который был передан методу Create, но я не могу понять, как извлечь параметры (такие как ContactRoleId, ContactId и т. д., как указано во фрагменте кода вызывающего метода create).

Итак, после всего этого я спрашиваю:

  1. Как я могу получить доступ к этим входным параметрам, чтобы убедиться, что в службу данных передаются правильные аргументы? Это вообще возможно?
  2. Есть ли лучший способ сделать это, чем то, что я сейчас пытаюсь сделать?

Решение

//Arrange
mockDataSupplierService.Create<ContactProductLink>(Arg.Do<Action<ContactProductLink>>(x=> actionToPopulateEntity = x));

//Assert
mockDataSupplierService.Received().Create<ContactProductLink>(Arg.Any<Action<ContactProductLink>>());
var entity = new ContactProductLink();
actionToPopulateEntity.Invoke(entity);
Assert.AreEqual(ExpectedContactId, entity.ContactId);

person CorrugatedAir    schedule 02.01.2013    source источник


Ответы (1)


Как я могу получить доступ к этим входным параметрам, чтобы убедиться, что в службу данных передаются правильные аргументы? Это вообще возможно?

По сути, вы не можете, так как невозможно извлечь детали «кода» из действия (подумайте, что происходит, когда вы передаете действие, которое не устанавливает никаких свойств — это полностью законно, но нарушит гипотетический механизм).

Однако вместо этого вы можете попробовать следующее:

  1. Создать сущность с начальными значениями
  2. Используйте аргумент Arg.Invoke, указывая NSubstitute использовать выбранный объект как параметр действия
  3. Убедитесь, что значения свойств объекта изменились

Например:

// Arrange
var entity = new ContactProductLink
{
    ContactRoleId = // ...
    // ...
};

mockDataSupplierService
    .Create<ContactProductLink>(Arg<ContactProductLink>.Invoke(entity));

// Act
// ...

Assert.That(entity.ContactRoleId, Is.EqualTo(2));
// ...
person k.m    schedule 02.01.2013
comment
+1. На самом деле есть две вещи, которые нужно проверить: вызов Create() и то, как работает переданное действие. Мы можем протестировать их отдельно, поймав действие, используемое с Arg.Do<ContactProductLink>(x => actionUsed = x). Другой вариант — сделать действие, переданное в Create(), общедоступным где-то и проверить ссылку на переданную ссылку. Затем действие можно проверить совершенно независимо. - person David Tchepak; 03.01.2013