Where should I test methods on an abstract class? - unit-testing

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.

Related

Unit Testing with Rhino Mocks

I have the following method called Execute() from the Abstract class called AutoLetterGenBatch in my ConsoleApp. I am trying to unit test this.
public void Execute()
{
BatchJobSecurity.Instance.CreatePrincipal();
DoExecute();
}
So I set up what I believe are all the proper references and try to invoke the method like below .
[TestMethod]
public void TestMethod1()
{
AutoLetterGenBatchJob ALGBJ = new AutoLetterGenBatchJob();
ALGBJ.Execute();
}
However, when I go to do the build it gives me this compilation error Error 34 Cannot create an instance of the abstract class or interface 'AutoLetterGenBatch.AutoLetterGenBatchJob' .
I am somewhat new to unit testing. I realize this probably isn't much of a test but I just want to see my Execute() method get hit for the time being. I have read that a good way to get around this problem with abstract classes is to set up a mock object for the abstract class. So I try to do this with RhinoMocks.
[TestMethod]
public void TestMethod1()
{
AutoLetterGenBatchJob ALGBJ = MockRepository.GenerateStub<AutoLetterGenBatchJob>();
ALGBJ.Execute();
}
It now builds with all of the proper using statements in place. However when the test runs I now get this error. Can't find a constructor with matching arguments . Again I am pretty new to this. If someone can help me to understand what it is I need to do it would be appreciated.
YOur first test doesn't make any sense, your class is abstract, by definition you can't create an instance of it. In order to test that method you need a class which derives from AutoLetterGenBatch and you then create an instance of this class and do what is neccessary to invoke the method on this instance.
Using a mocking framework would be one way, as would creating a test class of your own. Personally I would go with the 'roll your own' at first as this will be easier to debug.
public class TestAutoLetterGenBatch : AutoLetterGenBatch
{
}
once you have this class you'll see that you need to call the constructor that AutoLetterGenBatch declares. This is the same issue that rhino mocks it complaining about. Without seeing the class AutoLetterGenBatch we can't advise any further.
For what it is worth, Rhino mocks has seen little work recently and you would probably be better using Moq or another more active framework.
Also you need to generate a partial mock to do the testing you want to do, no a stub.

Salesforce Testing Abstract Class

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.

unit-test the template method design pattern

Suppose the following template method implementation:
public abstract class Abs
{
void DoYourThing()
{
log.Info("Starting");
try
{
DoYourThingInternal();
log.Info("All done");
}
catch (MyException ex)
{
log.Error("Something went wrong here!");
throw;
}
}
protected abstract void DoYourThingInternal();
}
Now, there are plenty of info around on how to test the Abs class, and make sure that DoYourThingInternal is called.
However, suppose I want to test my Conc class:
public class Conc : Abs
{
protected override void DoYourThingInternal()
{
// Lots of awesome stuff here!
}
}
I wouldn't want to do conc.DoYourThing(), since this will invoke the parent method, which was already tested separately.
I would like to test only the overriding method.
Any ideas?
You have labeled the question "tdd" but I doubt you've followed that principle when you encountered this "problem".
If you truly followed tdd your work flow would have been something like
Write a test for some logic not yet implemented
Impl the easiest possible impl for this test to make it green (logic on Conc1 for example)
Refactor
Write a test for some other logic not yet implemented
Impl the easiest possible impl for this test to make it green (logic on Conc2 for example)
Refactor
In "6" you might think that it would be a great idea to implement a template method because Conc1 and Conc2 share some logic. Just do it, and run your tests to see that the logic still works.
Write tests to verify the logic, don't base them how the implementation look like (=start with the tests). In this case, start writing tests verifying that the logic works (the logic later placed in your concrete types). Yes, that means that some code lines (the one in your abstract class) are tested multiple times. But so what? One of the point of writing tests is that you should be able to refactor your code but still be able to verify that it works by running your tests. If you later don't want to use template method pattern, in a ideal world your shouldn't need to change any tests, but just change the implementation.
If you start to think which code lines you test, IMO you loose much of the benefits of writing tests at all. You want to ensure that your logic works - write tests for this instead.
I assume part of the 'problem' is that there is no way to call a protected method from outside the class. How about a mock class which derives from Conc and provides a new public method:
public class MockConc: Conc
{
void MockYourThingInternal()
{
DoYourThingInternal()
}
}
I wouldn't consider DoYourThingInternal() to be separate from DoYourThing() (as in, two separate modules of code that can be tested in isolation) since you won't be able to instantiate your abstract class alone anyways and the 2 methods will always be run together. Besides, DoYourThingInternal() has access to all protected members of your class and could modify them, with potential side effects on DoYourThing(). So I think it would be dangerous to test DoYourThing() in complete isolation from a concrete implementation of DoYourThingInternal().
However, that doesn't mean you can't have separate tests for DoYourThing()'s expected behavior, which has to remain the same across all implementations of Abs, and DoYourThingInternal()'s expected behavior.
You could use an (abstract) base test class where you define a test for the general behavior expected from DoYourThing(). Then create as many test subclasses as there are implementations of Abs, with unit tests for the specifics of each implementation.
The test from the base test class will be inherited, and when you run any subclass's tests, the inherited test for DoYourThing() will also run :
public abstract class AbsBaseTest
{
public abstract Abs GetAbs();
[Test]
public void TestSharedBehavior()
{
getAbs().DoYourThing();
// Test shared behavior here...
}
}
[TestFixture]
public class AbsImplTest : AbsBaseTest
{
public override Abs GetAbs()
{
return new AbsImpl();
}
[Test]
public void TestParticularBehavior()
{
getAbs().DoYourThing();
// Test specific behavior here
}
}
See http://hotgazpacho.org/2010/09/testing-pattern-factory-method-on-base-test-class/
Don't know if abstract test class inheritance is supported by all unit test frameworks though (I think NUnit does).
What about sticking an interface on Abs and mocking it? Ignoring the calls, or set expectations on them?
You could do it several ways, many of which are documented here already. Here is the approach I typically take: Have the test case inherit from the concrete class.
public ConcTest : Conc
{
[Test]
public void DoesItsThingRight()
{
var Result = DoItsThingInternal();
// Assert the response
}
}
Hope that helps!
Brandon

How to unit test subclasses

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.

Should I test the Interface and All objects that implement it

Hi
Assume I have an Interface A and a class B that implements A. Within my test class I create a dummy class that implements A and I "test the Interface methods" now my question is should I test the methods that class B "gets" from the interface.
In my experience, you just test concrete classes and their interaction with interfaces.
That is, if you have concrete class B that implements A, you just test B and its interaction with other objects it references.
Generally testing should touch all (executable) lines of code. If you are implementing an interface it makes it that much easier, since you can code tests that form the "contract" of the interface and now the tests apply to all implementors of the interface.
This ensures consistency across all implementors. Should you encounter a situation where implementors behave differently (e.g. NullReferenceException vs. ArgumentNullException) you can add tests specifying which is "right" and which is wrong. This leads to less surprises down the road.
I might even go as far as saying that every interface should have a set of tests attached to describe the expected behaviour.
There are of course implementation specific things that can only be tested on the concrete implementor (e.g. "Was the file written?" vs. "Was the record comitted?"). These things should be provided through overriding or lambdas to the interface's test suite.
yes, you should aim to get 100% code coverage with your testing
Since your interface shouldn't have any concrete implementation then you don't need to test it since there is nothing to test by definition. The testing should be for the concrete implementation of the interface.
If you find yourself in a situation where you need to have a partial implementaton of an interface you can do what I do. For instance, say I have a interface of an item. This I call IItem and has all the interface. Then I declare an Item which is the partial implementation of the interface for common code and then ItemA, ItemB, etc. for the specialisations of Item.
I read all your posts I I think this solution works best.
Interface A
{
String A1();
String A2();
}
public class B:A
{
String A1(){return "A1"}
String A2(){return "A2"}
}
public class testB
{
public void B_Can_Return_A1()
{
A b=new B();
Assert.True(b.A1=="A1")
}
}
But if you are removing a method from an interface that the concrete implementations still rely on surely you shouldn't be removing that part of the interface?
This is true but this should still be enforced in tests i.e. tested. interfaces (should) play a big role in development and changes may create huge problems down the line. If an object implements an interface I think this is how it should be tested or something similar.
Please comment on this.