I want to mock a subclass method which is inherited.This method cannot be overriden since it's final.When using "when ,thenReturn " mockito is calling the real method which causes some exceptions and I want to avoid that.
class A{
final String doSomething()
{
//Some treatement
return "";
}
}
class B extends A{
//
}
class TestB {
#Test
public void test(){}
B b=mock(B.class);
when(B.doSomething()).thenReturn("");// it fails because it calls //the real method of A
}
}
There are two reasons why could be asking this questions:
a) you are dealing with some kind of 3rd party library/design that you can't change; but that you somehow want to test. In that case using PowerMock can be an option, as PowerMock manipulates byte code and makes it possible to mock final methods/classes. But: PowerMock is famous for creating all kinds of weird problems; and seriously: you are much better of not using it.
b) you are getting "unit testing" wrong: you never create a mock object of class B in order to test something on class B. You only mock objects X, Y, Z that your code in B needs to do something.
So, your real problem is: you have some method "doSomethingElse()" on B that you want to test. And "doSomethingElse()" calls "doSomething()" ... and your test fails because you can't control the behavior of "doSomething()". There are two options to get out of that problem:
1) Do you really need inheritance? Must B really extend A, or would it be better if a B object ... simply owned an A object? (if so, you can mock that A object and gain control over its methods). Ever heard about CoI?
2) You reverse dependencies; like in:
abstract class A {
final void doSomething() { doSomethingSpecific() ... }
abstract void doSomethingSpecific();
}
class B extends A { #Override void doSomethingSpecific() { ...
resulting in a "proper OO" solution to your "testing" problem.
Besides: if "doSomething()" is final on class A, then that should be in order to achieve OCP: you define some behavior on A that subclasses can use (or use indirectly) and that should not change. So, you can turn back to your design, and maybe that final was added "for the wrong reason", then it might be fine to simply remove the keyword.
Related
I'm trying to understand how to do unit testing with Mockito.
All the cases that I found is when a class A depends on a class B, that is A has an attribute of type B. I understand well this case. But how to do the tests when A uses B without getting it as attribute.
Suppose I have this code:
import package.classB;
public class A
{
public int methodA(classB b)
{
int x= b.methodB();
//do something with x and then return the result
}
}
How can I test the methodA? Do I need to use mocks in this case?
I suspect that this will turn into a philosophical debate, which it probably mostly is.
The answer is - it depends.
You can use a Mockito object, or you can just pass in a fully formed object as the argument. There are up and downsides to both.
Let's assume that ClassB is just a simple POJO. Something like a user record. It has a userID and a name field, and you want to test methodA. I would generally just create an instance of the user object and than pass that into the argument.
Your test might look like
public class TestA {
public void testMethodA() {
B b = new B();
int expectedValue = 1000;
A a = new A();
assertEquals(expectedValue, a.methodA(b));
}
}
The benefit of this is that you have a fully formed object B and you are testing with real data. The downside of this that is that Object B can be extremely complex or take long to generate. For example, Object B could be a database lookup.
If Object B needs to be mocked, it can be mocked with Mockito, and then you get lots of ways to work with it. The simplest case would be a variation of above.
public class TestA {
public void testMethodA() {
B b = Mockito.mock(B.class);
Mockito.when(b.methodB()).thenReturn(10);
int expectedValue = 1000;
A a = new A();
assertEquals(expectedValue, a.methodA(b));
}
}
The upside of this is that you don't worry about what happens in Object B. All you care about is that methodB in Object B returns a 10. You are just testing method A, which doesn't care that much about what Object B is doing. This can be much faster. The downside is that you are making assumptions about what Object A is doing with Object B. If Object A decided that it needed another method from Object B in methodA, your test would fail. It also might hide some of the implementation from Object B, which might become important in some cases.
Personally, I tend to try to mock as little as possible. This makes the setup of the tests more complex and it takes longer to run each test, but the upside is that I'm testing the whole process up to method A, starting from root data.
But there is nothing wrong with mocking Object B. Tests become simpler and possibly quicker, with the downside that you are making assumptions about object B.
In classes I would inherit these methods protected override, in order to change the behavior of the methods that it uses. Are shown below practice, correct? If not, why?
Simple type and immutable objects:
class A{
(...)
public int aA(){
int b=1;
return this.bB(b); // It is about this place.
}
protected int bB(int b){
b=2*b;
return b;
}
(...)
}
class B extends A{
(...)
#Override
protected int bB(int b){
return b-1;
}
}
In class A, I want to use a method bB() in method aA(), two methods are implemented in this class. The method bB () I put the "return" method aA(). Then B defines a class that inherits from A, and overrides the method bB(). As a result, the method aA() in class B works differently than the method aA() in Class A.
What if putting methods in return, which returns objects with the ability to modify?
As it is with putting static methods in return?
Whether this has any implications for concurrent programming?
You seem to be asking about whether the above code is the correct way to write a method that overrides a method in its superclass.
Yes it is the correct way to do it.
Yes, that is a good way to "change behavior" ... though you are only changing the behavior for the new class (B)
What if returned objects with the ability to modify?
Same answer.
As it is with returning of static and nonstatic methods?
No. Static methods are non-polymorphic. You cannot override static methods.
In your example, if bB was static then the #Overrides annotation would give you a compilation error. If you removed it, you would find that the call to bB() in aA would always call A.bB and never B.bB.
Note that calling a static method with the syntax this.someStaticMethod(...) is legal, but bad style. It looks like the call will be polymorphic but in fact it isn't.
Whether this has any implications for concurrent programming?
No particular implications.
On the other hand, if you are actually asking about methods that return other methods ... your example code doesn't do that.
I have a method like this:
public void someMethod() {
A a = new A(); // Where A is some class.
a.setVar1(20);
a.someMethod();
}
I want to test 2 things:
The value of Var1 member variable of a is 20.
someMethod() is called exactly once.
I have 2 questions:
Are those test objectives correct or should I be testing something else ?
How exactly do I test this using Mockito ?
You can't test that using Mockito, because Mockito can't access a local variable that your code creates and then let go out of scope.
You could test the method if A was a injected dependency of your class under test, or of the method under test
public class MyClass {
private A a;
public MyClass(A a) {
this.a = a;
}
public void someMethod() {
a.setVar1(20);
a.someMethod();
}
}
In that case, you could create a mock A, then create an instance of MyClass with this mock A, call the method and verify if the mock A has been called.
With your code, as it is, the only way to test the code is to verify the side effects of calling someMethod() on an A with var1 equal to 20. If A.setVar1() and A.someMethod() don't have any side-effect, then the code is useless: it creates an object, modifies it, and forgets about it.
Use JB Nizet's advice but note that order is important to you:
When verifying and order is important, use:
A mock = mock(A);
new MyClass(mock).someMethod();
InOrder order = inOrder(mock);
order.verify(mock).setVar1(20);
order.verify(mock).someMethod();
(Testing for exactly one invocation is the default in mockito).
Caution
This kind of test will be tightly coupled to the implementation. So do this in moderation. In general aim for testing state rather than implementation where possible.
Ad 1) Testing setters usually doesn't make much sense, but if you want to to then surely you have a getter on A to verify that var1 is set to 20?
Ad 2) You can use #Spy and verify() to test invocations on methods.
A spy = spy( a );
verify( spy , times( 1 ) ).someMethod();
Your example code is a bit terse, so my answer is very general - hope you can work with it.
Cheers,
For example, let's say this is my abstract class:
abstract class A{
int x;
int y;
void foo(A fooMe);
}
...and B and C are two classes which extend A.
What I want is for B to only be able to call foo() on other Bs, and for C to only be able to call foo() on other Cs. But I want this to be out of the hands of the programmer who's extending my A class - that is, I want a way to ensure this functionality within As code alone.
What can I do? (If possible) I'd like to avoid any hack or generics solution that's too messy - I still want foo to be able to be called like this, for example:
B b=new B();
B bb=new B();
bb.foo(b);
Edit: I'm now willing to accept a solution which uses generics, if anyone has any ideas... (I couldn't think of one)?
You could make foo be final in A, and implement it as follows: have it raise an exception unless fooMe.getClass() equals this.getClass(), and otherwise call abstract method fooHook. Of course, subclasses will have to override fooHook, not foo.
I believe the final-plus-hook approach is inevitable: if a subclass could override foo, there's no way A's code alone could guarantee that any checks performed in its foo aren't just going to be blithely bypassed by a subclass.
Here's a hack, but it's not compile time. I don't think Java generics don't have enough covariant/contravariant type support.
class B extends A {
#Override
void foo(A foome) {
if (foome.getClass() != getClass()) {
throw new UnsupportedOperationException("...");
}
}
}
You could enforce such a thing if you use aspect-oriented programming. Before advice could check and throw an exception for those cases that violated your requirements.
This is a general question on how to unit-test a Java Class using mock objects.
I can summarize my problem with this example. Let's say I've an Interface called MyInterface.java and a "TwoString" Object that doesn't override equals()
"TwoString.java"
private String string1;
private String string2;
public TwoString(String string1, String string2) {
this.string1 = string1;
this.string2 = string2;
}
...getters..setters..
"MyInterface.java"
void callMe(TwoString twoString);
Then I have "MyClass.java" Object. Its constructor accepts a concrete implementation of MyInterface.
MyClass methodToTest() contains the logic to create a TwoString oject in some way. Let's say that it will be created as
new TwoString("a","b")
So when methodToTest() is called it creates this TwoString object that will be passed to the Interface method callMe(TwoString twoString).
I basically want to mock the Interface. Create a MyClass object with this mock. Then verify that the mock method is called with a specific instance of TwoString.
I'm using EasyMock and this is some java code
"MyClassTest.java"
public void test() throws Exception {
MyInterface myInterfaceMock = createMock(MyInterface.class);
MyClass myClass = new MyClass(myInterfaceMock);
myInterfaceMock.callMe(new TwoString("a","b")); <--- fails here
expectLastCall();
replay(myInterfaceMock);
myClass.methodToTest();
verify(myInterfaceMock);
Here comes the problem. The TwoString object that I'm expecting in the call
myInterfaceMock.callMe(new TwoString("a","b"));
is different from the one generated in MyClass.methodToTest() because TwoString.java doesn't override equals.
I can skip the problem on the TwoString instance using
myInterfaceMock.callMe((TwoString)anyObject());
but I want to be sure that the interface method is called with a specific instance of TwoString that contains "a" as string1 and "b" as string2.
In this case the TwoString object is very simple and it will be easy to override the equals method - but what if I need to check a more complex object.
Thanks
edit:
I'll try to make it more readable with this example
public class MyClassTest {
private MyClass myClass;
private TaskExecutor taskExecutorMock;
#Before
public void setUp() throws Exception {
taskExecutorMock = createMock(TaskExecutor.class);
myClass = new MyClass(taskExecutorMock);
}
#Test
public void testRun() throws Exception {
List<MyObj> myObjList = new ArrayList<MyObj>();
myObjList.add(new MyObj("abc", referenceToSomethingElse));
taskExecutorMock.execute(new SomeTask(referenceToSomethingElse, ???new SomeObj("abc", referenceToSomethingElse, "whatever"))); <--- ??? = object created using data in myObjList
expectLastCall();
replay(taskExecutorMock);
myClass.run(myObjList);
verify(taskExecutorMock);
}
}
???SomeObj = object created by myClass.run() using data contained in myObjList.
Let's say that SomeObj comes from a third party library and it doesn't override equals.
I want to be sure that the taskExecutorMock.execute() method is getting called with a specific instance of that SomeObj
How can I test that the myClass.run() is actually calling the taskExecutorMock method with a correct instance
It is possible to use a custom equals matching method using org.easymock.IArgumentMatcher.
It should look something like:
private static <T extends TwoString> T eqTwoString(final TwoString twoString) {
reportMatcher(new IArgumentMatcher() {
/** Required to get nice output */
public void appendTo(StringBuffer buffer) {
buffer.append("eqTwoString(" + twoString.getString1() + "," + twoString.getString2() + ")");
}
/** Implement equals basically */
public boolean matches(Object object) {
if (object instanceof TwoString) {
TwoString other = (TwoString) object;
// Consider adding null checks below
return twoString.getString1().equals(object.getString1()) && twoString.getString2().equals(object.getString2());
}
else {
return false;
}
}
});
return null;
}
And is used as follows:
myInterfaceMock.callMe(eqTwoString(new TwoString("a","b")));
Some details may not be correct, but in essence it's how I've done it before. There is another example and more thorough explanations available in the EasyMock documentation. Just search for IArgumentMatcher.
First up - you probably mean "override equals" rather than implement, since all classes have some implementation of equals (the one they inherit from Object if they don't override anything else).
The answer in this case is simple - all value objects really really ought to implements equals and hashcode. Whether it's a simple one like TwoString, or the more complex object you allude to, it should be the object's responsibility to check whether it is equal to some other object.
The only other alternative would be to basically deconstruct the object in your test code - so instead of
assertEquals(expected, twoStr);
you'd do
assertEquals(expected.getStringOne(), twoStr.getStringOne());
assertEquals(expected.getStringTwo(), twoStr.getStringTwo());
Hopefully you can see that this is bad in at least three ways. Firstly, you're basically duplicating the logic that should be in the class' own equals() method; and anywhere that you want to compare these objects you'll have to write the same code.
Secondly, you can only see the object's public state, there could well be some private state that causes two apparently similar objects to be not equal (e.g. a Lift class could have a publically accessible "floor" attribute, but private "going up or down" state too).
Finally, it's a violation of the Law of Demeter for a third-party class to be basically messing about with the internals of TwoString trying to work out whether the things are equal.
The object itself should implement its own equals() method - pure and simple.
Take a look at Jakarta Commons Lang: EqualsBuilder.reflectionEquals()
While I agree with dtsazza that all value objects should have an equals() (and hashCode()) method, they're not always appropriate to testing: most value objects will base equality on a key, rather than on all fields.
At the same time, I'm leery of any test that wants to check all fields: it seems to me to be saying "make sure this method didn't change something that I wasn't planning for it to change." Which is a valid test, and on some level a very well-meaning test, but it's a little scary that you feel the need for it.
In this case the TwoString object is very simple and it will be easy to override the equals method - but what if I need to check a more complex object.
Once your objects start becoming so complex that you can't trivially check if they're equal from elsewhere, you should probably refactor and inject them as a dependency. This would change the design, but usually that's for the better.
You also seem to be relying on some knowledge of the internal behaviour of your classes. The above is an interaction test between two classes, which still sort of works, but the bigger your set of tested components gets, the less you can really still talk about "unit" tests. At a certain point you leave the realm of unit tests and you start doing integration tests, in which case you might be better off with a full blown test harness and isolating behaviour in certain places...
You can achieve this with argument captors in Mockito 1.8.
http://mockito.googlecode.com/svn/branches/1.8.0/javadoc/org/mockito/Mockito.html#15
I know you are using EasyMock but changing to Mockito is easy and it's much better!