I have an abstract class that features no abstract methods... How would one go about testing this? Can I simply import it into a test class and go about business as usual?
Example:
public abstract class SomeAbstractClass implements SomeOtherClass {
// Some variables defined here
private static final String dbUrl = System.getProperty("db.url");
// Some public methods
public String doSomethingToUrl(String url) {
url = url + "/takeMeSomewhereNice";
}
}
Say I pass in an arg for db.url of localhost:8080, and I wanted to test that the doSomethingToUrl method did output the new string... Would it still be in this format?
public class TestUrl {
SomeAbstractClass sac = new SomeAbstractClass();
#Test
public void testUrlChange() throws Exception {
String testUrl = "localhost:8080";
assertThat("localhost:8080/takeMeSomewhereNice",
sac.doSomethingToUrl(testUrl));
}
}
You wouldn't be able to create an instance of just SomeAbstractClass, no - but you could create an anonymous subclass:
private SomeAbstractClass sac = new SomeAbstractClass() {};
You may well want to create a concrete subclass just for the sake of testing though - so that any time you do add abstract methods, you just need to put them there.
While I suspect you could use a mocking framework for this, I suspect it would add more complexity for little benefit, unless you need to check under what situations the abstract methods are called. (Mocks are great for interaction testing, but can be brittle for other purposes.) It could easily make for more confusing error messages (due to the infrastructure involved) as well.
You cannot initialize an abstract class, so your test class wouldn't compile as is.
You can either use an anonymous instance (the example below should suffice):
SomeAbstractClass sac = new SomeAbstractClass(){};
However, I would actually recommend you mock the class by means of a mocking framework such as Mockito or EasyMock.
Related
I have a scenario in which I have to mock a method in parent class. The method is invoked from the method under test. I have not been able to mock the function using jMockit.
My super class is method is as follows
public abstract class SuperClass {
protected void emailRecipients(List<String> recipients) {
// Email recipients code. I want to mock this function.
}
}
My subclass is as follows
public class MyClass extends SuperClass {
public void methodUnderTest(HttpServletRequest request) {
// Some code here.
List<String> recipients = new ArrayList<>();
recipients.add("foo#example.com");
recipients.add("bar#example.com");
// This needs to be mocked.
this.emailRecipients(recipients);
}
}
I have tried using partial mocks using jMockit's tutorial, but it has not worked for me. My test method is given below.
UPDATE: I implemented Rogerio's suggestion as follows. The implementation still calls the real method. When I debug the instance of mocked class in Eclipse, this is what I see com.project.web.mvc.$Subclass_superClass#6b38c54e
#Test
public void testMethodUnderTest(#Mocked final SuperClass superClass) throws Exception {
final MyClass myClass = new MyClass();
new Expectations(myClass) {{
// .. Other expectations here
superClass.emailRecipients((List<String>) any);
}};
MockHttpServletRequest req = new MockHttpServletRequest();
myClass.methodUnderTest(req);
}
The issue is that when I try to mock the invocation of emailRecipients, it always tries to call the actual function. I am using Java 7, jMockit v1.35, and Maven 3x for our builds.
UPDATE The code is legacy code. As a result, we can't update it. We can not use PowerMock as it is not among the libraries that have been approved by the company. We can use either jMockit or Mockito or a combination of both.
The fact that you want to mock the method from parent class shows that your approach fails the Separation of Concerns/Single responsibility Pattern (SoC/SRP).
The use of PowerMock as suggested by Rajiv Kapoor is possible but this (as any use of PowerMock) would be a surrender to bad design.
You can solve your design problem by applying the Favor Composition over Inheritance principle (FCoI).
To do so you'd change your (most likely) abstract super class into a "normal" class. You'd create an interface that declares all the public and abstract methods in your super class. Your child class would no longer extend the parent class but implement the interface. It would get an instance of the former parent class as dependency and call it's methods providing common behavior as needed.
This dependency can easily mocked without the need of PowerMock.
UPDATE The code is legacy code. As a result, we can't update it.
In that case you are outruled.
The code you have is not unittestable because it is written in an untestable way. Your only chance is to write module and/or acceptance tests (without the use of a mocking framework) covering each and every execution path through your code.
This test will be expensive to create and slow but they will gurad your when refactoring the code to something testable (== changable) later.
see below example
P.S. use Mockito.any(HttpServletRequest.class)instead of Mockito.any(ArrayList.class) for your code
Super Class
public abstract class SuperClass {
protected void emailRecipients(List<String> recipients) {
System.out.println("Emailed!");
}
}
MyClass
public class MyClass extends SuperClass {
public void methodUnderTest() {
// Some code here.
ArrayList<String> recipients = new ArrayList<>();
recipients.add("foo#example.com");
recipients.add("bar#example.com");
// This needs to be mocked.
this.emailRecipients(recipients);
}
}
Test Class
public class TestCase {
MyClass myClass = Mockito.mock(MyClass.class, Mockito.CALLS_REAL_METHODS);
#Before
public void prepare() {
PowerMockito.doNothing().when(myClass).emailRecipients(Mockito.any(ArrayList.class));
/*PowerMockito.doAnswer(new Answer<Void>() {
#Override
public Void answer(InvocationOnMock invocation) throws Throwable {
System.out.println("Custom code");
return null;
}
}).when(myClass).emailRecipients(Mockito.any(ArrayList.class));*/
}
#Test
public void testMethodUnderTest() throws Exception {
myClass.methodUnderTest();
}
}
If you don't want the code in emailRecipients to execute then use doNothing()
else use doAnswer to execute some other code
I'm trying to add unit tests to some legacy code that has a String class name passed to it and that creates an object implementing a particular handler interface using Class.newInstance(String className). I can control the class name I'm passing, I can get a pointer to the new handler object (via a getHandler() call), and I would like to observe calls to it using Mockito.
My current solution is:
Create a new test class TestHandler that implements the interface.
Have that test class contain a Mockito mock object that also implements the interface.
Manually pass through all the interface methods to the mock object.
Make the mock object accessible via a getMock() method.
Observe the object by making verify() calls to objectUnderTest.getHandler().getMock().
This works, but feels a little inelegant, especially having to manually write all the pass-thru methods.
Is there a better solution?
Fundamentally, you're running into the same problems as trying to test a newly-created instance using new; the Class.newInstance (probably properly Class.forName(foo).newInstance()) doesn't hurt you, but doesn't help you either.
As a side note, your TestHandler sounds like a general purpose delegate implementation, which sounds pretty useful anyway (particularly if you ever need to write a Handler wrapper). If it is, you might want to promote it to be adjacent to your Handler in your production code tree.
Though I recognize that you mention legacy code, this becomes very easy if you are allowed to refactor to include a testing seam. (Ignoring reflective exceptions here for ease of explanation.)
public ReturnType yourMethodUnderTest(String className) {
return yourMethodUnderTest(Class.newInstance(className));
}
/** Package private for testing. */
public ReturnType yourMethodUnderTest(Handler handler) {
return yourMethodUnderTest(Class.newInstance(className));
}
You could also extract the object creation and replace it in your test:
/** Instance field, package-private to replace in tests. */
Function<String, Handler> instanceCreator =
( x -> (Handler) Class.forName(x).newInstance());
public ReturnType yourMethodUnderTest(String className) {
Handler handler = instanceCreator.apply(className);
// ...
}
You could even just extract it to a method and replace it in your test:
public ReturnType yourMethodUnderTest(String className) {
Handler handler = createHandler(className);
// ...
}
/** Package private for testing. */
Handler createHandler(String className) {
return Class.forName(className).newInstance();
}
#Test public void yourTest() {
// Manually replace createHandler. You could also use a Mockito spy here.
ObjectUnderTest objectUnderTest = new ObjectUnderTest() {
#Override Handler createHandler(String className) {
return mock(Handler.class);
}
}
// ...
}
Side note: Even though Mockito creates a named dynamic type, you almost certainly will not be able to hack it in and allow your code to create it by name. This is because the call to mock registers the instance within Mockito's internal state.
// BAD: Unlikely to work
#Test public void yourTest() {
objectUnderTest.methodUnderTest(
mock(Handler.class).getClass().getName());
// ...
}
Create a public method where you will place the logic to fetch the newInstance of the class
ClassA objectClassA=createNewInstance(className);
likewise,and
public ClassA createInstance(String className){
return (ClassA) (Class.forName(className)).newInstance();
}
Now suppose we were creating an instance of classA inside of ClassB
then in TestClass of B, we can simply mock this createInstance method
doReturn(mockClassA).when(mockClassB).createInstance(className);
Let's say there's a class that I use extensively and is returned by a method.
CommonClass obj = getCommonObject();
Now I want to extend this class to create some utility method to avoid repeating myself.
public CommonClassPlus extends CommonClass {
public String dontRepeatYourself() {
// the reason I'm creating a subclass
}
}
Of course I would like to use my improved class for the method above, however, downcasting isn't allowed.
CommonClassPlus obj = getCommonObject();
//Cannot cast to CommonClassPlus
How can I use the method dontRepeatYourself() if I can only work with the object that is an instance of the superclass?
CommonClass and getCommonObject() are from an external library and I cannot change them.
You cannot add behavior to an existing instance in Java (like you could in JavaScript, for example).
The closest you can get in Java is the Decorator pattern:
CommonClassPlus obj = decorate(getCommonObject());
where decorate() is
public CommonClassPlus decorate(CommonClass x) {
return new CommonClassPlus(x);
}
This approach creates a potentially huge amount of boilerplate because it must delegate each method call to the wrapped instance. If a method in CommonClass is final and there is no interface you can reimplement, then this approach fails altogether.
In most cases you will be able to get along with a simple static helper method:
public static String dontRepeatYourself(CommonClass x) {
...
}
If CommonClass is from an external library, you probably want to wrap it in an Adapter Pattern anyway, using the principle of Composition over Inheritance.
This gives you complete control if you want to, say, change the library you're using, and allows you to add functionality like dontRepeatYourself().
public class CommonClassAdapter implements MyAdapter {
private final CommonClass common;
private final String cachedResult;
// Note that I'm doing dependency injection here
public CommonClassAdapter(CommonClass common) {
this.common = common;
// Don't expose these because they shouldn't be called more than once
common.methodIOnlyCallOnce();
cachedResult = common.anotherMethodIOnlyCallOnce();
}
#Override
public void someMethod() {
common.someMethodWithDifferentName();
}
#Override
public String dontRepeatYourself() {
return cachedResult;
}
}
Note also that most modern IDEs have things like Eclipse's Source -> Generate Delegate Methods to make this process faster.
I am new to the EasyMock. I need to test my class using the EasyMock. but here the problem is my class has inner class and this inner class is instatiated in the outer class's method and calling the method of inner class by passing some parameters. I am not sure how to write the test case for this scenario.
Please help me write the test case for this.
Any help or suggetions are highly appreciated.
public class ServiceClass implements ServiceInterface {
public void updateUSer(USer) {
//some logic over here.
sendEmailNotice(subject, vTemplate);
}
private sendEmailNotice(subject, vTemplate) {
MimeMessagePrepator eNotice = new PrepareEmailNotice(subject, vTemplate);
MailSender.send( eNotice );
}
public class PrepareEmailNotice implements MimeMessagePrepator {
// some local variables.
public PrepareEmailNotice(subject, vTemplate) {
subject = subject;
vTemplate = vTemplate;
}
public void prepare( MimeMessage message) {
MimeMessageHealper helper = new MimeMessageHealper(message, true);
// setting the mail properties like subject, to address, etc..
}
}
Thanks.
First of all you need to think about what is the class responsibility.
At should it be doing with who should it be speaking?
Once you've clearly identified the dependencies you need to see how you can handle them in your code.
You might need do to perform some refactoring in order to conform to the dependency inversion principle.
For example here you have a dependency to the MailSender class but you won't be able to mock it as this dependency is "hard coded".
There is a good video about that: http://www.youtube.com/watch?v=XcT4yYu_TTs
The more I read mock example, the more I get confused...
I have classA method eat() that calls FatDude class eatThemAll()
public class classA {
FatDude dude = new FatDude();
public String eat() {
String result = dude.eatThemAll();
}
}
public class FatDude {
public String eatThemAll() {
return "never full";
}
}
Now I want to test classA eat() method by mocking FatDude class.
public class MockFatDude extends FatDude {
//override
public String eatThemAll() {
return "very full";
}
}
------------- test --------------
public class DoTest {
public void runTest() {
classA cl = new ClassA();
String out = cl.eat();
assertEqual(out, "very full");
}
}
This DoTest runTest() won't use MockFatDude class of course. One way I can think is to change the code to pass FatDude to eat() method of ClassA like:
public class classA {
public String eat(FatDude dude) {
String result = dude.eatThemAll();
}
}
Then change my test method to:
public class DoTest {
public void runTest() {
classA cl = new ClassA();
String out = cl.eat(new MockFatDude());
assertEqual(out, "very full");
}
}
But as you can see, I had to change the source code to meet my need.
Is this the right way to do? What if I am not allowed to change my source code?
I know if I apply TDD concept, it is OK to change source code but I would like to hear
some opinion or advice if what I have shown above is right way to do.
Mocking and the Dependency Inversion Principle (DIP) go hand in hand, and in most languages, Mocks work best by decoupling classes by means of interfaces.
In your instance, this will work without you needing to change code: (Edit : I mean, in future, if you design your app this way, you won't need to change code to mock dependencies :))
Abstract an interface IDude
Concrete classes FatDude (and MockFatDude) should implement IDude interface
provide a mechanism for an IDude instance to be 'set' or injected into classA - Dependency Injection (constructor or get / sets); or Service Locator pattern work best (to replace a concrete classfactory)
Also note that many mocking frameworks actually allow you to build up the Mock concrete class 'on the fly' (see MoQ et al), so you can create the functionality of MockFatDude directly in your unit test.
Yes. You've stumbled on some good design directly because of your unit test. If you look more closely, you'll see that you removed the coupling between classA and FatDude. Now FatDude can be an interface for behavior that gets passed in when needed. ClassA doesn't need to know what kind of FatDude it's getting, or how to construct a FatDude (with cheeseburgers?).
Your solution is exactly what I would have done. There's nothing wrong with changing your code to accomodate TDD, as long as you understand the reasons and the benfits/drawbacks to making such changes.