What is the best way to unit test subclasses? Let's assume there's a base class for which I've already written tests and there are some number of subclasses that override some of the parent's behavior in public and/or protected methods.
Should the test class for my subclasses extend (and override test methods where appropriate) the test class for my base class so that all of the base class tests are applied? Otherwise, I would expect to have repeated test code.
According to the Liskov substitution principle, instances of the subclasses, should exhibit the same properties as the base class, and, thus, pass (all ?) the same unit tests.
I would run [perhaps not all, all that are relevant] the base class tests for each subclass. This can be achieved with a test helper.
Yes, subclassing the test class could be a good way to avoid duplication in the unit tests. Have a look at the Testcase superclass pattern.
It is difficult to see without an example, but I would test the base class in one set of tests, and then create new tests for the subclasses and just test the behaviour that differs.
Related
I have an abstract class with some concrete and abstract protected methods, and I have a PHPUnit test for this abstract class.
Then I have classes that extend the abstract class and implement the abstract protected methods.
I'm curious of the smartest way to test that the child classes return what they need to return from the otherwise abstracted protected methods.
I have read a lot that you should not test private/protected methods, but I'm finding this awkward because to get code coverage across the protected method, I must replicate many of the tests from the abstract class test, which involves producing many mock objects and setting their methods to return specific values.
The end result will be a lot of tests that have very tight coupling to other classes. If I changes a class, the tests on for class need to change (totally ok), and then countless mock implementation of that class will need to change also.
At the end of the day, if the abstract class works, then I know my child object will work also, so long as it's implementation of the abstract protected methods returns an expected value.
So I'm wondering if I'm overlooking a pattern.
Duplicating tests across every child class doesn't seem to be better than testing that the child classes correctly implement their interfaces.
You are overlooking a pattern. It would be the Strategy Pattern. The protected methods of the child objects should be refactored into their own object with the protected method as a public method. You would then be able to test that these public methods return the correct thing.
Your tests for the base class would only need to change to have the mock object passed in. If your child classes are only implementing protected methods of the base abstract class. You can remove the abstract from the base class and have the children implement a strategy interface.
This will make your design more flexible. You would be able to easily extend the base class for other reasons and still have all of the previous functionality available to you.
This might be a noob question however, I am not entirely sure on the procedures to writing unit tests for an abstract class in Salesforce. The class itself has 3 public methods as well as two abstract unimplemented methods. I unfortunately haven't found much help on the topic.
I know abstract classes cannot be constructed which means I can't create an instance of it to test on. Greatly appreciate any inputs.
What ultimately worked for me was, I used a class that was already extending the abstract class to call the methods I needed to test. I didn't need a mock object or to create a whole new sub-class to test.
You could create a test subclass which would implement those abstract methods with dummy implementation.
That way, you can instantiate this test class in your test: calling its non-abstract methods will run the production code.
Alternatively, you could look into mocking frameworks: they might even remove the need to subclass the class yourself.
I am starting TDD both at work and at home (I know I'm late to the party). I already have several tests for public methods for classes. However many of the classes I write have lots of protected functions. When creating a test class, should I have it subclass the class to be tested so I can have coverage on the protected methods?
Thanks,
Jec
In an ideal world, you wouldn't need to test the protected methods directly, instead you would only be testing through the public interface. However, of course the world isn't ideal, and I don't think it's a bad thing to be testing protected methods if there is a good reason to.
I think whether to sub-class or not depends on the nature of the protected methods:
If they are abstract or blank methods designed to be overridden by a sub-class, and you want to test that the methods are being called, then a testing sub-class is a good way to do this, as you can use the sub-class as a way to intercept these method calls and verify how they were called etc. One thing I would say is to be careful that any logic in a testing sub-class is purely for the purpose of verifying method calls, otherwise you could introduce behavior which may impact your tests negatively (for example, you could easily add logic to a testing sub-class which causes a given test to pass based only on the logic in your testing sub-class, and not the logic in the real implementation).
If they are methods in a class designed to expose functionality to sub-classes, then I don't think that you need to sub-class the class under test. Because the methods are protected scope, different classes in the same package can access them, and therefore all you need to do is have your tests in the same package to call these methods to test them (which in my book is generally good practice, the tests should be in the same package but stored in a different directory).
Welcome. It's never too late for the party!
Creating sub-classes to get access to private or protected methods is perhaps the best way. It creates the maximum "surface" for you to construct your tests.
In other situations, I have created sub-classes to allow me to instrument a class under test, to add factory and singleton patterns to a class under test, and to help allow substitutions of mock objects.
You can subclass the class to test its protected interface.
Or you can let a mocking library do the subclassing. Depending on what the protected interface does, that may be preferable.
Specifically, if the base class uses the template method pattern, creating the subclass as a mock is probably better. If the base class just offers helper functions for the derived classes to use, consider putting them into a separate class and making them public.
You should test public interface of your class.
So you don't need to write unit test for private or protected members.
Your private and protected members are called inside public members so when you test your public members all private and protected members will be tested implicitly as well.
Many would argue that you should only test the public methods of a class.
Subclassing would work for protected properties and methods but would not work for private, internal, etc.
Depending on what language you use you can declare the test class and the class that it tests to be "friends" so the test class can see the other class' properties.
How do I mock non-overridden non virtual/virtual methods in a base class and test just the derived class's methods?
The case here is:
I have a base class X which has methods that connect to an external server and do a couple of other things.
I have a class Y derived from X. I have implemented two methods in Y. I want to just unit test them. I am worried only about these two methods and I don't want the base class implementation to be called to connect to the server etc( I want to mock those methods out , but i don't want to override those methods in my derived class Y and do nothing in them, since it is production code).
Any thoughts /ideas on how can I unit test my those methods in isolation?
P.S: I am using C++/GTest for development and unit testing.
One option is to create a Mock_base class and the class Derived inheriting from it in the test directory. Now mock out any implementations in the actual Base that you are not interested in with functions that do nothing. Example the Mock_base::Connect() may return SUCCESS return code. This way you can unit test the Derived:funcs() without modifying the source code.
You're really lucky you are having a hard time doing this!
Functionality is most of the time not intended to be reused through inheritance, and this is one good reason for that: your base class implements some interface that you want to mock out for a client (i.e. Y). Possibly, this functionality may later be implemented by some other class, too, and Y should be able to use that new, possibly better, implementation.
Y has/uses an X, but Y is not an X.
If your Y class needs to use X's functionality (connect to server etc...), it should aggregate it, not inherit from it.
You'll notice that the aggregation scheme allows for mocking just like that.
I have an abstract class that defines some methods. This class has two subclasses.
Should I create a fake subclass just for testing, or should I test the methods through the subclasses' tests? Testing through the subclasses seems more natural, but then I'd have to duplicate the test code between the 2 subclasses' tests.
What do you guys think?
You don't have to duplicate your test code - you can write your test methods so that they accept a parameter.
Since most test frameworks don't support tests that take parameters you can add a little wrapper that calls your parameterized test method with a specific instance. You can now easily choose whether it makes sense to call your test just once with some specific base class, or have multiple tests of the same method - one test for each of the possible base classes. Since only a thin wrapper needs to be added for each new test, there is very little code duplication.
void TestSomething(AbstractClass foo)
{
// Your test code goes here.
Assert.AreEqual(42, foo.Bar());
}
[Test]
void TestSomethingFoo1()
{
TestSomething(new Foo1());
}
[Test]
void TestSomethingFoo2()
{
TestSomething(new Foo2());
}
I would go for a minimal fake subclass, associating this with the Abstract Class. I like to think that the Abstract class is properly tested no matter what happens to any of the Concrete instantiations. This does assume that the code in the Abstract class is non-trivial and writing the fake class is not dispropoartionate work - with mocks I think this will usually be the case.