1

I'd like to know if somehow it is possible to set private readonly class variable via reflection or something?

Consider the following class:

public class TestSevice
{
    private readonly someClassType m_variable;

    public TestService()
    {
        m_variable = //call to some processing function
    }

    private static int CalculateStuff(int x, int y)
    {
        //some processing and return
    }
}

I'm writing a unit test for private static method CalculateStuff(int x, int y), which I'm able to call via reflection:

PrivateType pt = new PrivateType(typeof(AvatarService));
int actialRes = (int)pt.InvokeStatic("CalculateStuff", parameters);

The problem is that, for my unit test to work, I don't want to set m_variable or set it to null on invoking the static function.

So, is it possible with a constructor is parameterless ctor to not set m_variable or custom set to to something in the unit test?

Edit: Some details on //call to some processing function Here, a call is made to start the receiver of message queue.

The class TestService is instantiated on the start of worker role, and hence the queue receiver is started in the ctor. The message queue receiver then calls a wrapper function in TestSevice class, which in turn calls CalculateStuff. And since I just want to test the core business logic, I don't want to start queue receiver(which imposes certain dependencies).

Flair
  • 2,899
  • 5
  • 21
  • 22
  • 1
    Couldn't you inject this into the constructor? I'm new to unit-testing but I'm pretty sure that's the whole notion of what unit testing is about anyway? EDIT: Apologies, I mis-read, you want to set this on calling the static function. I don't believe this is possible (I could be wrong), it seems you're battling against the whole purpose of the `private` access modifier. –  Jul 18 '14 at 14:26
  • See also http://stackoverflow.com/questions/7075938/making-a-private-method-public-to-unit-test-it-good-idea?rq=1 – lc. Jul 18 '14 at 14:28
  • 1
    Wait, what is the relationship between a static method and an instance field? Am really confused as why does it matter? – Sriram Sakthivel Jul 18 '14 at 14:30
  • 3
    Even if setting a private variable is possible, you shouldn't do it, because it goes against the idea of unit testing. Your tests should never break encapsulation, no matter what goal you are trying to achieve. – Sergey Kalinichenko Jul 18 '14 at 14:31
  • The underlying problem is that you are *doing work in your constructor*, that's not a good idea. See guidelines here: http://msdn.microsoft.com/en-us/library/ms229060(v=vs.110).aspx – Ian Mercer Jul 18 '14 at 14:33
  • @dasblinkenlight: I understand your point, but here `m_variable` is starting some service queue which is not required for my unit test. Also, I know that private methods are not for unit test but in this case the method is private just because it is not used anywhere out of its class. @IanMercer: Sure, but unfortunately I didn't write the class, so can't change it. – Flair Jul 18 '14 at 14:42
  • @dev_wired You can make the private method `internal` then, and add visibility of internals to your unit test assembly. – Sergey Kalinichenko Jul 18 '14 at 14:46
  • It sounds like you'll have to do some refactoring. This often happens when you try to unit test legacy code. This gets really tricky with static methods calling other static methods (I assume that's effectively what's happening at //call to some processing function). What you really want to be able to do is stick an interface there and mock out that functionality. Alternatively, you could move the logic in CalculateStuff to another class, test that class, and call that class from your current CalculateStuff. Last choice may be to create #if debug switch in the constructor. – Adam47 Jul 18 '14 at 15:02
  • @Adam47 Thnx for the suggestion, that would be the last alternative to put the logic in other class for testing purpose and use `CalculateStuff` only as a wrapper. You can see my edit for some details on `//call to some processing function` – Flair Jul 18 '14 at 15:23
  • While I hate to admit it, I've had to use #if debug many times to make unit testing possible in legacy systems. When you're trying to introduce unit testing, the surest way to have management squash it is to break something in production while refactoring to make code more testable. – Adam47 Jul 18 '14 at 15:36

2 Answers2

1

If you are trying to test a class by modifying its behavior you have already missed the point.

If there is a way that class can get into a certain test then that's how you should test it. With read only the only way to do that is through a constructor.

If the property is read only it suggests you only want to instantiate it once for a specific instance of that class and know it can't change. If that's the case the you shouldn't want to change it but possibly instantiate another instance.

If it needs to be changed before each call on calculate and you are in a situation where you think you need the function to be static, then you should probably have it as an extra parameter. This means it can longer be read only. Doing it this way would disconnect it from the state of a given instance but if you are trying/need to change the value it shouldn't be read only.

tam
  • 1,583
  • 2
  • 13
  • 25
0

Apparently the answer is yes. https://stackoverflow.com/a/934942/2540156 But that doesn't really sound like your issue. It sounds like you want an alternate constructor to call during unit testing that will prevent the code from running that sets your variable. For that you'll have to make a change to your constructor.

Community
  • 1
  • 1
Adam47
  • 196
  • 7