2

As far as I understand, there are two main methods to test a class.

  1. test class to extend the class under test
  2. test class to create the class under test (composition)

As far as I can tell, the first method is considered to be a bad practice.

but why is that?

IsaacLevon
  • 2,260
  • 4
  • 41
  • 83
  • 1
    https://www.petrikainulainen.net/programming/unit-testing/3-reasons-why-we-should-not-use-inheritance-in-our-tests/ – NeplatnyUdaj Apr 16 '19 at 10:07
  • 1
    Instances of the class `FooTest` do not need to be instances of `Foo`. There should never be a situation in which you want to use an instance of `FooTest` in place of an instance of `Foo`. – Andy Turner Apr 16 '19 at 10:17
  • @AndyTurner, one advantage could be exposing protected methods but I guess that it is considered a bad practice as well (to test protected methods) – IsaacLevon Apr 16 '19 at 10:32
  • A `protected` method being protected, the test is not "necessary", but the test of all `public` method, using a `protected` one is required – AxelH Apr 16 '19 at 10:34
  • You can read [junit & java : testing non-public methods](https://stackoverflow.com/questions/440786/junit-java-testing-non-public-methods) about the test of non-public methods. It should answer your question about why this is not required to inherite the class you are testing. Now, the answer to your question is mostly opinion based, in my "opinion" so I don't believe we can answer about "bad practice" easily – AxelH Apr 16 '19 at 10:35
  • 1
    UnitTest verify the *public observable desired behavior* of the Code under test. By *public* is meant that other production code calls this methods. This does not imply that the code under test exposes this behavior through `public` annotated methods, but usually it does. – Timothy Truckle Apr 17 '19 at 07:18
  • In practice, neither of the two options you describe (inheritance / composition) are used. Instead, the test class contains test methods where inside the test methods an instance of the class under test is created as a local temporary object. Sometimes the test class contains an object of the class under test as a member object, such that with `Setup` functions some amount of code duplication can be avoided, but that is a very testing specific use of composition. – Dirk Herrmann Apr 20 '19 at 23:49
  • 1
    Regarding tests of private/protected etc. stuff: Unit-testing is about finding bugs. Bugs are in the implementation - different implementations, different possible bugs. Think of Fibonacci as iterative/recursive function, closed form expression (Moivre/Binet), lookup table: The interface is always the same, the possible bugs differ significantly. Also, when looking at coverage, you always look at the implementation, not the interface. How you design your classes such that you truly can test also the implementation details is a different story... – Dirk Herrmann Apr 20 '19 at 23:56

1 Answers1

1

For me, Unit Test have 2 main purposes:

  1. verify the testobject is doing what I expect it to do
  2. document how to use the tested class correctly

By extending the tested class, the test seams likely to change the classes behaviour. This is bad practic for testing. Sometimes I even do it to fix for example current time dependency like this if DI is no option:

   private InstanceToTest instance;
   private Calendar now = new GregorianCalendar(2019, 4, 4, 13, 23, 47);
   @Before
   public void initInstance() {
      instance = new InstanceToTest() {
         @Override
         Calendar getNow() {
            return now;
         }
      };
   }

Now I can test against 4th of April 2019, 13:23:47 to make the test stable.

Sometimes I want to test extracted inner methods separately. I prefer to make these method package private. This way I can call them from my test (if it's in the same package whithin the test source folder) without overwriting them.

Markus Kreth
  • 748
  • 7
  • 26