Переопределение защищенного абстрактного метода в NSubstitute - PullRequest
0 голосов
/ 01 апреля 2019

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

Идея состояла бы в том, чтобы заменитель с помощью переопределенного метода, который я мог бы использовать для мониторинга принятых вызовов и т. Д., Как обычно, с насмешкой. Но как этого добиться с помощью NSubstitute?

Я бы предпочел не расслабляться ни protected, ни abstract модификаторами.

Вот что я хотел бы сделать:

[Test]
public void Items_Add_shouldCall_ItemAddedMethod()
{
    var sut = Substitute.For<ItemsRepository>();
    // how to configure???
    sut.Items.Add(Substitute.For<IItem>());

    sut.Received().ItemAdded();  // currently cannot do this

// ...

public abstract class ItemsRepository
{
    public ObservableCollection<IItem> Items { get; set; } 
        = new ObservableCollection<IItem>();

    // ...

    protected abstract void ItemAdded();
}

1 Ответ

2 голосов
/ 02 апреля 2019

API NSubstitute полагается на вызов метода для настройки его на Returns или проверки Received() вызовов, что означает, что для стандартного использования мы можем работать только с вызовами, которые могут быть вызваны через публичный API (за исключением protected и private членов). С частью вашего вопроса abstract нет проблем; нормально использовать NSubstitute с доступными abstract членами.

Несмотря на то, что C # по своей природе не позволяет нам напрямую взаимодействовать с protected участниками, NSubstitute все еще записывает вызовы, сделанные этим участникам. Мы можем проверить это, используя "неофициальное" .ReceivedCalls() расширение:

public abstract class ItemsRepository {
    public virtual void Add(int i) { ItemAdded(); }
    protected abstract void ItemAdded();
}

public class Fixture {
    [Fact]
    public void CheckProtectedCall() {
        var sub = Substitute.For<ItemsRepository>();
        sub.When(x => x.Add(Arg.Any<int>())).CallBase();

        sub.Add(42);

        var called = sub.ReceivedCalls().Select(x => x.GetMethodInfo().Name);

        Assert.Contains("ItemAdded", called);
    }
}

Другие варианты включают создание производного класса (как указал @Nkosi) или создание элемента internal вместо protected и использование InternalsVisibleTo, чтобы сделать элемент доступным для вашего тестового кода (если вы делаете последний Я рекомендую установить NSubstitute.Analyzer , чтобы убедиться, что он настроен правильно).

...