0

This is probably a damn fool question, for which I apologise, but I can't seem to get the google syntax right to find an answer.

Imagine a Property, like this:

private int _type
public int Type
{
    get { return _type; }
    set 
    {
        _type = value;
        //raise an event in your chosen language or tech
        CallAFunction();
    }
}

Now, imagine that CallAFunction does some sort of fairly serious heavy lifting in your application, interacting with the database via a repository.

It doesn't seem unreasonable to want a unit test for this, to make absolutely sure that Type gets set to whatever you put in and to check that doing so raises the expected event.

However, setting the property with a test will call CallAFunction() which means that you're no longer really testing a "unit" of code as such, and perhaps more importantly that a very simple test for this very simple property might well require more elaborate preparation, including repository mocking, which seems huge overkill.

In some cases you could split these apart by having CallAFunction raised via the event. But that's not always the case (I'm using WPF, and the events bubble up to non-testable XAML).

What's the best way to split these two interdependent things apart?

Bob Tway
  • 3,606
  • 3
  • 21
  • 26
  • The usual way is to provide a fake `CallAFunction()` so that the test controls its behaviour and doesn't involve the real environment. – mouviciel May 08 '14 at 08:53

1 Answers1

4

There are two issues intermingled here.

  1. "Is it OK to have hidden logic in a setter?" This is asked from time to time, and there is no accepted universal answer. It depends on whether the additional thing you do is really an intrinsic part of that property or not.
  2. "How do I test a method with an expensive external dependency?" Here the general opinion is that if your method does stuff via a collaborator, you should either mock that collaborator out, or use it normally while making sure that this does not make your unit test unacceptably slow.
Kilian Foth
  • 107,706
  • 45
  • 295
  • 310
  • Nice linkage. OK, regarding point two, (and apologies for stupidity) - am I right in thinking that I can't mock out CallAFunction unless I put it in a different object? You can't mock functions in the same object you're testing, right? – Bob Tway May 08 '14 at 08:58
  • 1
    Not the call itself, but if you are actually talking to a repository of some sort, then whatever `CallAFunction()` does will eventually cross class boundaries, and that is where mocking can strike. – Kilian Foth May 08 '14 at 09:02
  • That goes back to my original point - it seems a lot of overhead to test a property, and CallAFunciton already has its own tests. But I guess the answer you're implying is that there is no easy/best approach to this. – Bob Tway May 08 '14 at 09:07