2016-12-30 4 views
0

Я использую nj4x и имеет класс, который имеет поля только для чтения следующим образом.Как насмехаться/переопределить поля readonly для модульного тестирования

public class MarketInformation 
    { 
    public readonly double ASK; 
    public readonly double BID; 
    public readonly double DIGITS; 
    public readonly double EXPIRATION; 
    public readonly double FREEZELEVEL; 
    } 

Я пишу модульные тесты для классов и методов, записывающих эти классы. Для изоляции/издевки я использую Nsubstitute и MicrosoftFakes (главным образом, прокладки). Я хочу переопределить эти поля, поэтому, когда они вызываются в моих методах, я получаю предсказуемые результаты для тестирования. Я создал прокладку для этого класса, но все, что он мне предоставляет, - это конструктор, который теперь позволяет мне инициализировать его. Есть ли способ установить эти поля извне этого класса?

+0

Я не очень хорошо осведомлен о насмехах/подделках и т. Д., Но это не значит, что вы задали свои жестко запрограммированные предсказуемые значения для своих полей * внутри * класса mock, то есть вам не нужно проходить это или назначить его извне. Предполагается, что макет должен * быть * реализацией абстракции, которую вы издеваетесь, так же как «настоящий» класс находится в реализации. –

+0

@ rory.ap реализация mocks - это отдельная идея, однако я использую рамки для насмешек и изоляции. Реализация макетов требует абстрактных/интерфейсных классов. однако они недоступны здесь. –

+1

Вам нужно создать интерфейс, который вы можете издеваться. Члены должны быть «виртуальными». (NSubstitute может работать только с виртуальными членами класса, поэтому любой не виртуальный код в классе будет выполняться!) [Ссылка] (http://nsubstitute.github.io/help/creating-a-substitute/) – NtFreX

ответ

0

Возможно, вам понадобится создать класс-оболочку со своими собственными свойствами get, чтобы заглушить или закрепить. Вы можете создать свой собственный интерфейс, если хотите использовать заглушки (не показаны).

public class MarketInformationWrapper : MarketInformation 
{ 
    ... 
    public double Ask 
    { 
     get { return ASK; } 
    } 
    ... 
} 
+0

Я сомневаюсь, что это не принесет мне никакой пользы. Это будет работать только тогда, когда я могу передать объект в тестируемый класс или метод. То, что я хочу, это то, что делают прокладки. Как я создаю прокладку для манекена класса, скажем, shimDummy. то я могу просто сказать shimDummy.AllInstances.Ask = (Dummy) => 5; таким образом я получаю 5 всякий раз, когда он вызывается. –

2

Это не очень, но если у вас есть доступ к экземпляру, который должен быть изменен, вы можете использовать the SetField method of the PrivateObject class. Класс PrivateObject является частью платформы тестирования модулей MS.

Например, рассмотрим класс:

public class ClassWithReadOnly 
{ 
    public readonly string Foo; 

    public ClassWithReadOnly() 
    { 
     Foo = "bar"; 
    } 
} 

Вы можете установить поле только для чтения, как так:

var test = new ClassWithReadOnly(); 
Console.WriteLine("Before Foo == '{0}'", test.Foo); 
var po = new PrivateObject(test); 
po.SetField("Foo", "oof"); 
Console.WriteLine("After Foo == '{0}'", test.Foo); 

Выход будет:

Перед Foo = = 'bar'

После Foo == 'oof'