I am trying to unit-test a class that extends an abstract base class.
Here are the "similar classes" for illustration purposes:
public abstract class MyAbstractBaseClass {
#Autowired
private WaterFilter waterFilter;
protected List<String> filterComponents(List<String> allComponents) {
return waterFilter.filter(allComponents);
}
}
public class MyDerivedClass extends MyAbstractBaseClass {
public List<String> filterWater(List<String> allWaterComponents) {
List<String> filteredComponents = this.filterComponents(allWaterComponents); //calls abstract class's filterComponets()
filteredComponents.add("something-else");
return filteredComponents;
}
}
Here is the unit test I am trying:
#RunWith(EasyMockRunner.class)
public class MyDerivedClassTest {
#TestSubject
private MyDerivedClassTest SUT;
#Before
public void setup() {
SUT = new MyDerivedClassTest();
}
#Test
public void test filterWater_HappyCase() {
//I want to mock my abstract class's filterComponents() method
//I am trying this:
EasyMock.expect(SUT.filterComponents(getDummyComponents())).andReturn(getSomeComponents());
//What to replay here?
//EasyMock.replay(...)
List<String> actualResult = SUT.filterWater(getDummyComponents());
//assert something
//What to verify?
//EasyMock.verify(...)
}
}
When I run this test, I get
java.lang.NullPointerException
in MyAbstractBaseClass.filter(allComponents)
I understand that the autowired "waterFilter" is not getting initialized. But then, I just want to mock the "non-abstract" method of the abstract class in my unit test.
How should I go about this using EasyMock? Also, I don't know what to replay() and verify().
When you write an unit test, you test a object (generally, a method of it) and you may mock a object (generally, a method of it).
However, you should not unit test and mock the same object because in a some way, it seems not very natural : if you test a method of a class, the behavior of the tested class should stay as natural as possible and not fake its own methods.
Otherwise, we can wonder if the quality of the unit test is good.
Why ? Because it doesn't reflect the real behavior of the class that we would have at the runtime, but just some part of its behavior.
In a unit test, isolation is researched but behind it, the idea is to isolate your under test class only from the other classes and not an isolation of its own behavior.
Of course, you can try to mock a no-abstract method in the abstract class of your under tested class but the design and the quality of your test may become less good.
In your case, I imagine two reasons to mock the no-abstract method in the abstract class :
the waterFilter field dependency annoys you because it is not valued, so an exception (NullPointerException) is raised during the test.
You really want to mock the no abstract method in the abstract class because you have already unitary tested this method and you don't want to duplicate this test.
1) If your the problem is the waterFilter field dependency.
you should mock the waterFilter field. To mock a field, it must be accessible and modifiable. In your case, it's not straight because the field is private.
So, you have two ways to access to it to be able to mock it :
change your design to give the possibility to set the field from a public method or in the constructor of MyDerivedClass.
use reflection to set the field (use an API or do it yourself because it's not hard).
You don't need to do verify operations with EasyMock. Just mock the result returned by waterFilter.filter(allComponents) such as :
waterFilterMock.filter(mockedComponents)
In this way, the mock returns the value you have chosen and in your JUnit assertion, you are able to do the correct assertion for your method under test.
Just for information, you could use Mockito instead of EasyMock. It's more flexible and it offers more readable operations.
For example, you could do it with Mockito :
Mockito.when(waterFilterMock.filter()).thenReturn(mockedComponents);
As you can see, it is more readable.
2) If you problem is that you really want to mock the no-abstract method in the abstract class because you have already unitary tested it
You should modify your design and use composition instead of inheritance. You would have not MyAbstractBaseClass any longer but simply a dependency between two classes (the one has a field of the other). In this way, you could mock the filterComponents() method in a natural way.
Expectations has to be set on mocked resources.
In your case i think you should inject a mocked instance of WaterFilter.
And your expectation,replay and verify should be set on waterFilter object instance.
You can refer to the example provided in given below link.
http://www.tutorialspoint.com/easymock/easymock_junit_integration.htm
Related
I am new to Unit testing and trying to figure out the different implementations of testing. I m trying to figure out how to mock a particular function call. I came across Mock Spy but didn't quite understand how it's been used. Can someone tell me how mocking is done in such cases...
Class ABC {
void display(String name, int id){
validateName(name);
validateId(id);
}
}
Class TestIt{
#Test
void testValidation(){
//how to mock validateName function call and test only validateId ?
ABC obj=new ABC();
obj.display("abc",2);
}
}
Some mocking frameworks allow partial mocks (most of the mocked class is actuall the real thing, just some methods are mocked). If your example is anywhere near the real code, I would not test the two methods separately. If one of these methods do something that is not wanted in a test, like accessing an external service (DB, webservice, filesystem), the I would encapsulate that functionality into an adapater class and inject it into ABC. Then you can mock the adapter.
My class under test is ClassA which in one of its private method uses a static factory (lets say CarFactory) method getCar(XXX xxx) which returns a Car.
Part of the CarFactory logic is to validate that the given xxx parameters meets some criteria.
I tried using Mockito like the following:
#Mock private Car mockForCar;
#Mock private XXX xxxMock;
...
when(CarFactory.getCar(xxxMock)).thenReturn(mockForCar);
But I get an exception regarding that xxxMock isn't valid by the CarFactory.
Why is the real getCar(xxx) method gets called and not the stubbed one?
Is there a better way doing this?
From the Mockito FAQ:
Can I mock static methods?
No. Mockito prefers object orientation and dependency injection over
static, procedural code that is hard to understand & change. If you
deal with scary legacy code you can use JMockit or Powermock to mock
static methods.
If you want to stub this using Mockito, you should make it non-static and inject the factory. And that's better OO design anyway.
I have what amounts to a lightweight test framework written as a JUnit Abstract test. What I would like to do is have the implementing subclasses each define their custom test class setup. My plan was to have the abstract superclass define an #BeforeClass method that calls into an abstract setup method that each subclass would be forced to define, but this fails as the #BeforeClass methods must be static and static methods cannot be made abstract nor can they call instance methods.
I could just assume that subclasses will do the setup by including what's required in the documentation or by throwing an IllegalStateException, but I'd really like to be able to enforce this at an interface level for a number of reasons. Can anyone think of a work around for this?
By the way, I had the same issue with making these tests parameterized (subclasses define the parameters, but #Parameters annotated methods must be static). I got around this by running with the 3rd party JUnitParams runner which allows method level parameters. Check it out here: https://github.com/Pragmatists/JUnitParams
One option is to have subclasses implement a, say, static doSetupOnce() method, and find and invoke that method reflectively from the base class #BeforeClass method. Since this needs to be a static method, its existence can only be enforced at runtime.
Another approach would be to have an abstract doSetupOnce instance method in the base class which gets invoked the first time the parent's #Before method gets invoked. This enforces the issue at compile time, but then implementors will have to be careful not to access instance fields from this method (since this is probably not what they want).
In general (and without knowing the details of your situation), I'm not very fond of either of these approaches, and would rather leave it up to implementors to declare a #BeforeClass method if needed. Locking them up in a rigid base class scheme can cause more problems than it solves. Also consider the use of JUnit rules, which often are a better choice than base classes (e.g. because they are composable). Of course you can also combine the two approaches, relying mainly on JUnit rules and additionally offering some base classes with predefined rules for convenience.
For your main question, why not make your parent class abstract and use the #Before annotation instead of #BeforeClass ? For example:
public abstract class TestParent {
#Before
public void setup() {
doSetup();
}
protected abstract void doSetup();
// other stuff...
}
public class RealTest extends TestParent {
protected void doSetup() {
// custom setup
}
// custom tests...
}
This will force the subclasses to redefine the doSetup() method without using static methods.
This may be out of scope or overkill, but I think it's worth mentioning since they're not that different. So I'm taking a leap of faith and suggest that you could try TestNG because methods annotated with #BeforeClass do not have to be static, nor do those annotated with #Parameters.
You can read about the differences between the 2 frameworks here and it looks like they also have support for migrating JUnit tests to TestNG
I don't think it is possible to do this in a clean OO way. Not only is #BeforeClass a static method, but JUnit will call the parent's #BeforeClass before the child's #BeforeClass.
Anyway you try to do this must necessarily expose the parent class's internal static state so a child class can set the parent's fields, breaking encapsulation.
I think the best way is to to use #Before, but also have a static flag that sets if the method has been called before, that way at least you can short circuit and only do the initialization for the first call...
public class SupportController{
public void disableUserAccount(String username) throws Exception {
UserAccount userAccount =
new UserAccount(Constants.SYSTEM, Constants.CONTAINER, username);
UserAccount.disableAccount();
}
}
How would i test that the useraccount created is disabled?
I would suggest using Mock Objects.
Besides that, you can check the JUnit FAQ, where you can find a section about testing methods that return void.
Often if a method doesn't return a value, it will have some side
effect. Actually, if it doesn't return a value AND doesn't have a side
effect, it isn't doing anything.
There may be a way to verify that the side effect actually occurred as
expected
There are three basic solutions:
Use a factory class that can be mocked
Use PowerMock which can mock calls to constructors
Update the class to use a default scope or protected scope factory method which could be overridden in a test env.
PowerMock does not always play well with other runners (for example SpringJUnit4TestRunner). I usually avoid it for this reason and the fact that it modifies the compiled code.
The overridable factory method is another option. To do this you must extend the class and override the factory method. This means that the test is running against an instance of the class under test that is not actually the class under test but a testable subclass. This has test-smell to me so I tend to avoid it where possible.
The factory class method is my preferred solution. Pass in a Factory class that be default creates the UserAccount. In your test provide a mocked (I use Mockito) version of the factory.
I want to unit test a class, Class A, but it has a dependency on another class that uses a user session method. The method that I want to test does not involve user session. Can I make helper method in Class A that would replicate the behavior of the Class B method that I need?
I know it's not clear, let's dig some code to get clear understanding....
public void testDetails() throws Exception
{
//Some logic that generates DetailsTOList
saveDetailsHelper(DetailsTOList);
int detailsSize = getDetailsSize();
assertNotNull(detailsSize);
}
Now getDetailsSize() get size information from a database. Class B has this method, but I cannot create an object of Class B and test this method since Class B gets session information from User, and I can set session information from JUnit class.
I have created saveDetailsHelper method that replicates behavior of Class B - saveDetails() method, and am calling that in testDetails() method as shown above.
My question:
can we have helper methods in junit class?
What is best approach to deal with this situation?
JUnit classes function like every other class in java; you're welcome to have helper functions. The only thing that determines whether other functions will be run is (depending on the version of junit) whether or not there is an annotation instructing the harness to run it as a test.
However, this problem is precisely why you should design your classes carefully. If Class B calls out to a database for information, this is a great opportunity to compartmentalize that functionality. You don't clarify 'dependency' (are you extending?), but if Class B is a component of Class A, you can create a whole stub class that is a stand in for Class B, and returns hardcoded (or otherwise coded) data specifically for the testing of class A. As long as the signature of the Class B proxy is the same, you can have confidence Class A works.
It is often useful to make these inner classes of your test class, to keep things from getting too messy in your workspace.
public class testA {
#Test
public void testDetails {
ClassA a = new ClassA();
a.setDependency(new StubClassB());
//run your test
}
private class StubClassB() extends ClassB {
public boolean saveDetails() {
//return fake information;
}
}
}
Helper methods will not have the #Testcase annotation. You would write the test code just like any other code, but would include only the relevant methods for testing, and validate only relevant portions of that test method.
You can put the helper method in the test class, omit the Testcase annotation and call it where needed (ad hoc per method or in your setup if it's needed for all tests). But probably a better solution is to use something like JMock to represent Class B and give back desired results.