20 May 2008

Комплексна перевірка параметрів за допомогою Rhino.Mocks (Callback)

В Rhino.Mocks є достатньо цікавий функціонал для перевірки вхідних параметрів, це Callback.

Коротко це метод який приймає делегат, який виконується на час виклику. По правилам цей метод повинен повернути true якщо все добре, або false якщо навпаки.

Головна проблема це сигнатура делегату, вона повинна повертати булево значення, і приймати копію параметрів. Зрозуміло кожного разу можна писати новий делегат. Але набагато цікавіше скористатися дженериками ;).

Далі все просто, це дженеріки які нам потім знадобляться:


public delegate bool Verify<T1>(T1 obj1);
public delegate bool Verify<T1, T2>(T1 obj1, T2 obj2);
public delegate bool Verify<T1, T2, T3>(T1 obj1, T2 obj2, T3 obj3);
public delegate bool Verify<T1, T2, T3, T4>(T1 obj1, T2 obj2, T3 obj3, T4 obj4);

До речі, можна такі дженеріки і не писати, адже .Net 3.5 вже має універсальні делегати:


public delegate TResult Func<TResult>();
public delegate TResult Func<T, TResult>(T arg);
...
public delegate TResult Func<T1, T2, T3, T4, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4);

А це код який їх використовує, я до речі, тут використовую Lambda Expressions:


sourceService.UpdateItem(null, null);
            LastCall.On(sourceService)               
                .Callback(
                new Verify<SourceAnchor, DataItem>(
                    (anchor, item) =>
                        {
                            Assert.IsNotNull(anchor, "Anchor should not be null");
                            Assert.AreEqual(sourceId, anchor.SourceId, "Anchor should have predefined source ID");
                            Assert.AreEqual(discoveryUri, anchor.DiscoveryUri, "Anchor should have predefined URI");                           
                            // Always return true because we use assertions instead of relaying on return results
                            return true;
                        }
                    )                   
                )
                .Repeat.Any();

Або якщо не подобається лямбда, можна скористатися старим добрим синтаксисом:


.Callback(
    new Verify<SourceAnchor, DataItem>(                   
        delegate(SourceAnchor anchor, DataItem item)      {                           
            Assert.IsNotNull(anchor, "Anchor should not be null");
           //...
            return true;
        }
    )
)

До речі, чесно кажучи не знаю чим опікувались розробники, але повертати булево для перевірки параметрів, це дуже погана ідея. Ми самотужки викидаємо всю інформацію, стосовно того що скоїлось. Для того щоб обійти цю халепу, я і використовую асерти прямісінько в методі перевірки.

 

Коментарі

# usarskyy said:

А чи є такий функціонал у TypeMock.NET?

P.S.: у фразі "...чим опікувались розробники..." краще вжити слово "керувались" :)

21 May 08 at 1:18 AM
# Mike Chaliy said:

Про TypeMock.NET, навіть не знаю. Так щось на кшталт цього повинно бути, можливо просто реалізація інша.

Про "опікувались" vs "керувались" теж нічого сказати не можу, мені більше подобається "опікувались" ;). До цього часу я "керувались" не чув в такому контексті.

21 May 08 at 2:13 AM
# usarskyy said:

Не так давно Mike Chaliy опублікував пост про перевірку параметрів за допомогою Rhino.Mocks . Так як

22 May 08 at 6:10 AM
# Mike Chaliy's Blog said:

Нещодавно я писав про комплексну(функціональну, за допомогою коду) перевірку параметрів метода. Сьогодні

22 May 08 at 7:25 AM
Анонімні коментарі деактивовані. Увійдіть або Зареєструйтесь щоб мати доступ до ресурсів Спільноти.

About Mike Chaliy

Вчу українську, багато працюю. Цікавлюсь моделюванням небезпек. Більшість часу витрачаю на .Net.