0

In the code below I have a class Foo which is called (without an interface) by my main method. There is no backing field or setter for the property, instead it calls a private method. Foo cannot be changes, nor can the usage of foo be changed to an IFoo interface.

- How do I change the value of foo.FooValue?

- Is there anything in the System.Reflection, System.Reflection.Emit, .NET standard libraries etc (unsafe code, whatever) that I can include in a unit test to change the return value?

I appreciate if there is something it's bound to be quite "evil", but I am interested in "evil" answers.

public class Program
{   
    public static void Main(){

        Foo foo = new Foo();
        int bar = foo.FooValue;
    }
}

public class Foo{

    public int FooValue
    {
        get
        {
            return this.FooMethod();
        }
    }

    private int FooMethod
    {
         return 0;
    }
}

Related questions:

How to set value of property where there is no setter - Related but unanswered - Maybe the answer is "no", but I'm not convinced by the top answer which merely points out you can't achive this by changing a (non-existent) backing field.

Intercept call to property get method in C# - Interesting. Not sure whether this is my answer and if it is, not sure how it could be used in a unit test.

EDIT: Okay. I'm going to re-write my code to make it more testable. However, out of interest, has anyone out there successfully hacked their way through this situation?

Community
  • 1
  • 1
Nathan Cooper
  • 6,262
  • 4
  • 36
  • 75
  • Do you own the `Foo` class? You hardcoded it to return 0. Add a property or field, then get it to return the property and add a setter. – mason Feb 26 '15 at 15:58
  • So your interest is just for unit testing? Are you essentially trying to "mock" `Foo` by changing its behavior? – D Stanley Feb 26 '15 at 15:59
  • @mason I don't own the Foo class. I would rather not refactor and if I was to refactor I would decouple Foo from my code by using at as an IFoo. – Nathan Cooper Feb 26 '15 at 15:59
  • @DStanley Basically, yeah. My three steps were: can i mock it (no), can I reflect it (no), lets go look at the implementation. – Nathan Cooper Feb 26 '15 at 16:00
  • Are you wanting to test the value of `FooValue` or something else that _depends_ on `FooValue`? – D Stanley Feb 26 '15 at 16:04
  • @DStanley I'm calling a method that internally makes a comparison against FooValue. More or less `if(foo.FooValue == valueInLocalScope)`. This determines where the execution goes. – Nathan Cooper Feb 26 '15 at 16:07
  • Moles should be able to do at least part of what you are looking for - http://www.bing.com/search?q=microsoft+unittest+moles ... I've not used it - so can't tell if it covers all your needs. Opinion: I'd prefer to refactor code to be testable (if it is under your control)... – Alexei Levenkov Feb 26 '15 at 16:10
  • @AlexeiLevenkov Interesting. I found a [tutorial (pdf)](http://research.microsoft.com/en-us/projects/pex/molestutorial.pdf) but I'm not sure how moles could solve this particular situation. Do you have enough knowledge about moles ( / the time) to jot down an answer? – Nathan Cooper Feb 26 '15 at 16:14
  • @NathanCooper - no, that's why it is comment... I never had case where I *had to* use it and like it this way :) – Alexei Levenkov Feb 26 '15 at 16:21

1 Answers1

3

You could create a proxy for Foo that could be mocked:

public class FooProxy : IFoo
{
    private Foo _Foo;
    public FooProxy(Foo foo)
    {
        _Foo = foo;
    }
    public int FooValue
    {
        get {return _Foo.FooValue();
    }
}

public interface IFoo
{
    public int FooValue {get;}
}

then you can use DI to "inject" an IFoo and make your code more testable.

D Stanley
  • 149,601
  • 11
  • 178
  • 240
  • Thanks for the answer. I know my code would be more testable if it used interfaces. It doesn't in general for dtos (foo is a dto where someone has been a bit enthusiastic in giving it implementation). If I did do this I would probably just use Moq rather than a proxy. So your answer to my question is: "your code is untestable, there is no trick to mock Foo outside of a refactor"? – Nathan Cooper Feb 26 '15 at 16:11
  • 1
    @NathanCooper - I like the way you spin the answer :) - there is nothing lightweight in .Net to deal with intercepting calls to non-virtual/non-interface methods. IL-rewrites of some sort is highest abstraction layer where you can achieve that, using debug interfaces or custom JIT/runtime to be distant next... – Alexei Levenkov Feb 26 '15 at 16:18
  • @Nathan Your program is tightly coupled to `Foo` - if you need to test your method with something other than `Foo` the correct approach is to break the tight coupling. There may be low-level ways (IL rewrites, etc.) but they are just bypassing the real problem. – D Stanley Feb 26 '15 at 16:30