0

I have a class with multiple protected methods, properties and fields. Let's say this is the class:

    public class UntestedClass
    {
        protected int field;
        protected int Method() => field + 5;
    }

I want to test the class but I have to make all members of that class accessible to my test methods. There are two ways that I know of:

  1. Subclass UntestedClass, override protected methods with public ones and add methods or properties to access protected fields. I do not like this way as it is too much tedious work.
    public class MyTestedClass : UntestedClass
    {
        public int Field {get => base.field; set => base.field = value; } // Now accessible as public
        public new int Method() => base.Method();                         // Now accessible as public
    }
  1. Inherit UntestedClass in my Unit test class. This approach takes care of tedious work but it makes it impossible to test different constructors.
    [TestClass]
    public class TestsOfTests : UntestedClass
    {
        [TestMethod]
        public void MethodTest()
        {
            base.field = 1;            // Assign to protected field
            var result = base.Method();// Invoke protected method
            .... and so on ...

Is there a better way? Ideally, I would love to have something like this:

   var testable = new MakeEverythingPublic<UntestedClass>();
   testable.field = 42;

I do not believe this is possible but maybe there is a third way that is better than the two choices I listed above?

Optional Option
  • 1,261
  • 8
  • 26
  • The class do not have any public methods? – Chetan Ranpariya Sep 27 '19 at 01:12
  • 3
    You generally only test the public interface of a class. – Rufus L Sep 27 '19 at 01:13
  • I rarely need to do this, I would test the class and its functionality, and if i really needed to this id reflect out the properties. But in general hitting this kind of issue may be a sign that there in a SRP problem, or insufficient coverage – TheGeneral Sep 27 '19 at 01:13
  • 3
    Possible duplicate of: https://stackoverflow.com/questions/9122708/unit-testing-private-methods-in-c-sharp. I like this part of the accepted answer: *"If you are finding you need to test a lot of private behavior, most likely you have a new 'class' hiding within the class you are trying to test, extract it and test it by its public interface."* – Rufus L Sep 27 '19 at 01:13
  • @RufusL is taking you in the proper direction...I might extend his first comment to say: _"generally you only *directly* test (i.e. write unit tests) for the public interface of a class; conversely, the private portions of a class we expect will get tested *indirectly* during the direct testing of the public interface (thus, it is not typically needed to write unit tests for the private parts). Think about it -- any private method of a class is only visible / callable to other code within same class -- test all public methods and you indirectly any private code they call. – David Tansey Sep 27 '19 at 01:27
  • So, the proper direction is no testing? – Optional Option Sep 27 '19 at 01:31
  • Here's a decent write-up about the fascinating and subtle subject of _What to Test and What Not to Test_ . This one is just a couple of pages and gives a decent explanation in that space. https://dzone.com/articles/unit-testing-guidelines-what-to-test-and-what-not – David Tansey Sep 27 '19 at 01:31
  • 1
    You asked _"so, the proper direction is no testing?"_ More specifically _"no direct testing of private methods_" is the proper direction in the vast majority of cases. Some given development/code situation might be one that falls outside of 'typical' and then perhaps it could be justified -- but I don't think you are probably in a situation like that. I think I can safely say that I am certain that you will never have a situation where it is appropriate to unit test ALL private methods -- so which one(s) can you think of a justification for? None? Maybe... – David Tansey Sep 27 '19 at 01:38
  • Public methods are complex. Private/protected methods may have a few branches that can be covered by running a few tests. The topmost public methods are just too complex to cover all possible code branches. – Optional Option Sep 27 '19 at 01:48
  • _"Public methods are complex"_ -- they shouldn't be. If they are, your class is probably too complex. You should be testing the public interface of your objects. And those tests should provide complete code coverage. Which means that all the private implementation details will get tested, without a need to test each private method individually. I understand the temptation to test them on their own, but as already noted multiple times, if your code is so complex that you have private implementation details you feel need to be tested individually, those details probably belong in their own class – Peter Duniho Sep 27 '19 at 03:03
  • Now public methods with "do not call this" comments make sense :) – Optional Option Sep 27 '19 at 03:47

0 Answers0