NSubstitute поддерживает параметры ref? - PullRequest
5 голосов
/ 24 сентября 2010

У меня есть следующая сигнатура метода в моем интерфейсе:

void SetItem(ref AddressItem item);

Я делаю ограничение параметра следующим образом:

IAddAddressForm form = Substitute.For<IAddAddressForm>();
AddressItem item = null;
form.SetItem(Arg.Is(item));

Но это не удается из-за ссылки.Если я возьму ссылку, то она работает нормально.Но мне нужно перейти по ссылке здесь.

Есть идеи, как это получить?

Примечание: Моя конечная цель - создать исключение в SetItem, если переданное значение равно нулю.Если вы можете помочь с этим, то вы получите дополнительные очки!

1 Ответ

10 голосов
/ 25 сентября 2010

NSubstitute не имеет прямой поддержки параметров ссылок, совпадающих с аргументами arg, но в целом он будет работать с ними нормально.

Я предполагаю, что вы должны использовать ref, как указано в вашем вопросе,но, очевидно, если вы сможете избежать ref, ваш API будет проще, как и его тестирование (независимо от используемых вами фреймворков).

В ответ на ваш ближайший вопрос вы можете передать ссылку, обновив свой второйПример кода:

form.SetItem(ref item);

В качестве примечания, убедитесь, что вы не пытаетесь использовать слишком много поведения для замены.Я обнаружил, что всякий раз, когда я делаю это, это признак того, что мне нужно упростить связь между классом, который я тестирую, и его зависимостями.(Или, если мне действительно нужно много логики в поддельном объекте, я передам один код, а не сгенерирую его; часто это может быть проще.)

Есть несколько способов заставить этот вызов броситьисключение:

form.When(x => x.SetItem(ref item)).Do(x => { throw new ArgumentNullException(); });

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

form.WhenForAnyArgs(x => x.SetItem(ref item))
    .Do(x => {
        if (x[0] == null)
            throw new ArgumentNullException();
    });

Наконец, если вы просто хотитечтобы проверить, правильно ли реагирует тестируемый вами класс, когда IAddAddressForm выдает исключение arg null, я, вероятно, просто сделаю следующее:

form
    .WhenForAnyArgs(x => x.SetItem(ref item))
    .Do(x => { throw new ArgumentNullException(); });

Таким образом, вам неважно, что это за аргумент,хотите убедиться, что код, который вы тестируете, правильно реагирует на этот случай.

Надеюсь, это поможет.

SIDE ПРИМЕЧАНИЕ:

Если вы хотитеиспользуйте аргумент arg (например, Arg.Any<AddressItem>()) для аргумента out или ref, который вам необходимо определить вне самого вызова (это может быть немного подвержено ошибкам: вам необходимо убедиться, что вы определилиСопоставители в том же порядке, в котором они войдут в вызов):

        IAddAddressForm form = Substitute.For<IAddAddressForm>();
        AddressItem item = Arg.Is<AddressItem>(y => y.Number == 14);
        form
            .When(x => x.SetItem(ref item))
            .Do(x => { throw new ArgumentNullException(); });
        var address = new AddressItem { Number = 14 };
        form.SetItem(ref address);
...