How to mock/ override readonly fields for unit testing

6.3k views Asked by At

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?

2

There are 2 answers

1
doobop On

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; }
    }
    ...
}
0
Jack A. On

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'