1

I am using nj4x and it has a class that has readonly fields as follows.

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

I am writing unit tests for classes and methods writing these classes. For isolation/ mocking I am using Nsubstitute and MicrosoftFakes (shims mainly). I want to override these fields so when they are called in my methods I get predictable results for testing. I generated shim for this class but all it provides me is a constructor, now allowing me to initialize it still. Is there any way to set these fields from outside this class?

Usama Aslam
  • 437
  • 7
  • 18
  • I'm not very knowledgeable with mocks/fakes etc. but isn't the idea that you set your hard-coded predictable values for your fields *inside* the mock class, i.e. you don't need to pass it in or assign it from outside. A mock is supposed to *be* an implementation of the abstraction that you're mocking, just like the "real" class is in an implementation. – rory.ap Dec 30 '16 at 13:40
  • @rory.ap implementing mocks is a seperate idea however, I am using frameworks for mocking and isolation. Implementing mocks require abstract/interface classes. however those are not available here. – Usama Aslam Dec 30 '16 at 13:45
  • 1
    You need to create an interface which you can mock. The members need to be `virtual`. (NSubstitute can only work with virtual members of the class, so any non-virtual code in the class will actually execute!) [reference](http://nsubstitute.github.io/help/creating-a-substitute/) – NtFreX Dec 30 '16 at 13:51
  • I am using nj4x library. Cannot create interfaces. – Usama Aslam Dec 30 '16 at 13:54
  • Then I would recommend to switch to a mocking library which supports non virutal members ([reference](http://stackoverflow.com/a/11738228/6583901)). Why do you eaven need to mock fields? This shouldn't be a use case.. – NtFreX Dec 30 '16 at 13:55
  • public double GetAskPrice(SymbolType sym) { // other code return _conn.Gc.Marketinfo(sym.DisplayName).ASK; } Like in this method Marketinfo(sym.DisplayName) is an instance of this class. I need that double value ask, to make this method independant of MarketInformation class. MarketInformation gets values from server, always changing. I need more predictable results for testing. – Usama Aslam Dec 30 '16 at 14:00

2 Answers2

3

It isn't pretty, but if you have access to the instance that needs to be modified, you can use the SetField method of the PrivateObject class. The PrivateObject class is part of the MS unit testing framework.

For example, consider the class:

public class ClassWithReadOnly
{
    public readonly string Foo;

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

You can set the read-only field like so:

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);

The output will be:

Before Foo == 'bar'

After Foo == 'oof'

Community
  • 1
  • 1
Jack A.
  • 4,245
  • 1
  • 20
  • 34
1

You'll probably need to create a wrapper class with your own get properties to stub or shim it out. You could create your own interface if you wanted to use stubs (not shown).

public class MarketInformationWrapper : MarketInformation
{
    ...
    public double Ask
    {
        get { return ASK; }
    }
    ...
}
doobop
  • 4,465
  • 2
  • 28
  • 39
  • I doubt it won't do me any good. This will work only when I can pass the object into class or method under test. What I want is something what shims do. Like I create a shim for class dummy, say shimDummy. then I can just say shimDummy.AllInstances.Ask = (Dummy) => 5; this way i will get 5 whenever it is invoked. – Usama Aslam Dec 30 '16 at 14:11