2015-02-24 5 views
7

Я хочу сделать mock метод расширения, но он не работает. Как это может быть сделано?NSubstitute mock extension метод

public static class RandomExtensions 
{ 
    public static IEnumerable<int> NextInt32s(this System.Random random, int neededValuesNumber, int minInclusive, int maxExclusive) 
    { 
     // ... 
    } 
} 

[Fact] 
public void Select() 
{ 
    var randomizer = Substitute.For<DefaultRandom>(); 
    randomizer.NextInt32s(3, 1, 10).Returns(new int[] { 1, 2, 3 }); 
} 
+2

AFAIK Вы не можете высмеивать метод расширения с помощью бесплатных mocking frameworks. Потому что методы расширения - это просто статические методы, и вы не можете издеваться над статическим методом со свободными насмешками. TypeMock делает это, я думаю (но это не подлежит сомнению). –

ответ

3

NSubstitute не может издеваться над методами расширения в соответствии с комментарием Шрирама, но вы все равно можете передать издевательский аргумент методу расширения.

В этом случае класс Random имеет виртуальные методы, поэтому мы можем издеваться над ним непосредственно с NSubstitute и другими инструментами для издевательства на основе DynamicProxy. (Для NSubstitute, в частности, мы должны быть очень осторожны классы насмешливо. Пожалуйста, ознакомьтесь с предупреждением в the documentation.)

public static class RandomExtensions { 
    public static IEnumerable<int> NextInt32s(this System.Random random, int neededValuesNumber, int minInclusive, int maxExclusive) { /* ... */ } 
} 
public class RandomExtensionsTests { 
    [Test] 
    public void Select() 
    { 
     const int min = 0, max = 10; 
     var randomizer = Substitute.For<Random>(); 
     randomizer.Next(min, max).Returns(1, 2, 3); 

     var result = randomizer.NextInt32s(3, 0, 10).ToArray(); 

     Assert.AreEqual(new[] {1, 2, 3}, result); 
    } 
} 
+0

Я пробовал это, но макет не возвращает {1,2,3}, а переходит в код/​​* ... * /. См. [Gist] (https://gist.github.com/anonymous/a27d3bd572d8abdaf4770805b93eefdb) – Damian

+0

@Damian Он работает только в том случае, если метод расширения вызывает обманный объект. В сущности 'NextInt32s()' нужно будет вызвать 'random.Next (minInclusive, maxInclusive)'. –

+0

В структуре dotnet Random.Next (min, max) возвращает int, а не массив int. Предупреждение нового к C#! – Damian

-1

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

+0

Да, но если я определяю интерфейс для DefaultRandom и издеваюсь над ним, то он не видит метод расширения NextInt32s. Как я могу сделать? – user3526923

0

Да, вы можете издеваться, если вы создаете интерфейс, такой как IRandom и расширить интерфейс вместо фактической реализации , Тогда вы должны быть в состоянии обмануть интерфейс в своем тестовом классе.

public interface IRandom 
{ 
} 

public class Random : IRandom 
{  
} 

public static class RandomExtensions 
{ 
    public static string NextInt32s(
     this IRandom random, 
     int neededValuesNumber, 
     int minInclusive, 
     int maxExclusive) 
    { 
    } 
} 

В тестовом классе оный:

IRandom randomizer = Substitute.For<IRandom>(); 
var result = randomizer.NextInt32s(3,0,10); 

С помощью этого процесса вы просто издеваетесь интерфейс не фактический класс.

Смежные вопросы