How to test a method that is invoking methods of another class? - java

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.

Related

Is it preferable to pass the whole object or call a method on it and pass the returned value?

I am providing the examples below to further illustrate my point:
Example 1:
public class A {
public String getTheNeededString() {
String returnedString;
//logic goes here
return returnedString;
}
}
public class B {
public void doSomething(A objectA) {
String neededString = objectA.getTheNeededString();
//proceed to do something that needs the above String
}
}
public class Client {
public static void main(String[] args) {
A objectA = new A();
B objectB = new B();
objectB.doSomething(objectA);
}
}
Example2:
public class A {
//stays the same
}
public class B {
public void doSomething(String neededString) {
//proceed to do something that needs the above String
}
}
public class Client {
public static void main(String[] args) {
A objectA = new A();
String neededString = objectA.getTheNeededString();
B objectB = new B();
objectB.doSomething(neededString);
}
}
I guess that there might not be a "better" approach and it might be a matter of preference.
If that's the case, then I would really appreciate any opinion/preference on the matter.
It is always preferable to pass only the required info for following reasons:
Single-responsibility principle : Each class/method should have one and only one responsibility. In this case, the method doSomething() should only know how to transform a string input into the desired output. It should not be the responsibility of this method to get the string by calling other methods.
Loosely coupled design: Imagine you decide to change the getTheNeededString() method in a way that you have to change all the calls to this method in your project. You'll have to make changes in doSomething() method as well. Here, the doSomething() method is tightly coupled to getTheNeededString() method. This is not a good design.
I believe it really is a matter of preference, and dependent on what exactly you need the program to do.
I would advise with Example 2, as it just makes more sense to me. If I were to come across your code at a later date and trying to interpret it, the second approach would be much more intuitive, at least for me.
It also makes the code reusable in the case you need to perform that same operation with any String outside of Object A. That may not be the case, but I still do not see the need to pass in the entire object. Pass the bare minimum input needed to produce the output needed.
Assume the method is to, say, count the number of occurences of the letter 'Z' and is called with countOccurencesOfLetterZ(objectA). Now, any person just exposed to this code will have to inspect this method to find out what it does - sure, the name is very intuitive.. but you're passing in the entire object, which needlessly creates uncertainty/confusion as to what you're trying to accomplish.
Now, assume you have countOccurencesOfLetterZ(objectA.getUsername()). I no longer have to inspect that method to figure out what you're trying to accomplish. Even better, if this method ends up being something you can utilize outside of Object B, then you can put it in a utility class and reuse that code for any string.
It depends on what is the goal of each class in your design.
Just an example.
Suppose class A represents a product and provides some details based on which class B creates product description. Suppose this logic is more complex that just getting a string. If you encapsulate such logic into the class B (approach 1), then if the logic changes later on, the only place to adjust will be the class B. The effort will be small and the number of bugs also small, if any. In case of the 2nd approach you will have to find all places where you pass data of object of class A to the object of class B and adjust all of them. It will take more time. Also it can happen, that you do these changes slightly differently and introduce more bugs. In such cases 1st approach is preferable.
Suppose the goal of the class B is to translate a given message key to some language, e.g. according to the default locale. In such case this class does not need to know where this key comes from (to reduce dependency on other classes). Suppose you have also other classes that provide keys that need to be translated, but they are in different class hierarchies and such objects cannot be passed to the method of class B. Then the 2nd approach is better. Each place where B is called implements its specific logic and passes to B only the common part, String key.

Mocking locally created objects in java using Mockito2

I am writing module tests for a project using testng and Mockito2. I want to mock a few methods which make outbound requests. Now, the object to mock is created locally within another object's method. So, if I have say, 4 classes, A, B, C and D, such that A creates an object of type B, B creates an object of type C and so on, and object of type D is to be mocked, I see I have two options to mock it.
Option 1 is to spy on objects of type A,B,C and inject spy of B into A and C into B and finally inject mock of of D into C during object creation. Following is an example.
class A {
public B createB()
{
retrun new B();
}
public void someMethod ()
{
B b = createB();
}
}
In this way I can can spy on A and inject mock object for B when createB is called. This way I can ultimately mock D.
Option 2 is to not mock intermittent classes and directly have a Factory class like the one below:
class DFactory {
private static D d;
static public void setD (D newD)
{
d = newD;
}
public static D getD()
{
if (d!=null)
{
return d;
} else
{
return new D();
}
}
}
The above option is simple, but I am not sure if this is the right thing to do as it creates more static methods, something that should be avoided, I believe.
I would like to know which method should be preferred and if there is some other alternative.
Please note that I do not wish to use powermockito or any other such frameworks which encourage bad code design. I want to stick to mockito2. I am fine with refactoring my code to make it more testable.
The way you have it now, with A creating B and B creating C and C creating D, all of that creation are implementation details you can't see or change, specifically the creation of dependency objects.
You are admirably avoiding the use of PowerMockito, and you are also admirably interested in refactoring your code to handle this change well, which means delegating the choice of D to the creator of A. Though I understand that you only really mean for this choice to happen in testing, the language doesn't know that; you are choosing a different implementation for the dependency, and taking the choice away from C's implementation. This is known as an inversion of control, or dependency injection. (You've probably heard of them before, but I introduce those terms at the end because they typically associated with weight and frameworks that aren't really necessary for this conversation right now.)
It's a little trickier because it looks like you don't just need an implementation of D, but that you need to create new implementations of D. That makes things a little harder, but not by much, especially if you are able to use Java 8 lambdas and method references. Anywhere below that you see a reference to D::new, that's a method reference to D's constructor that could be accepted as a Supplier<D> parameter.
I would restructure your class in one of the following ways:
Construct A like new A(), but leave the control over the implementation of D for when you actually call A, like aInstance.doSomething(new D()) or aInstance.doSomething(D::new). This means that C would delegate to the caller every single time you call a method, giving more control to the callers. Of course, you might choose to offer an overload of aInstance.doSomething() that internally calls aInstance.doSomething(new D()), to make the default case easy.
Construct A like new A(D::new), where A calls new B(dSupplier), and B calls new C(dSupplier). This makes it harder to substitute B and C in unit tests, but if the only likely change is to have the network stack represented by D, then you are only changing your code as required for your use-case.
Construct A like new A(new B(new C(D::new))). This means that A is only involved with its direct collaborator B, and makes it much easier to substitute any implementation of B into A's unit tests. This assumes that A only needs a single instance of B without needing to create it, which may not be a good assumption; if all classes need to create new instances of their children, A would accept a Supplier<B>, and A's construction would look like new A(() -> new B(() -> new C(D::new))). This is compact, but complicated, and you might choose to create an AFactory class that manages the creation of A and the configuration of its dependencies.
If the third option is tempting for you, and you think you might want to automatically generate a class like AFactory, consider looking into a dependency injection framework like Guice or Dagger.

Mock parent final method

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.

Testing a void method with Mockito

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,

How does mockito help in reducing test cases

Assume you have three classes A, B, and C where A calls B and B calls C and every class has some number of internal states that influence the result given by the class' methods. Describe how using Mockito can considerably reduce the number of test cases for class A.
I am new to Mockito. I sort of got the concept of Mockito but stumbled upon the above question for which I do not have an answer.
Mockito can help you isolate a class' behavior without having to know the internal workings of a collaborating class.
Assume C looks like this:
public class C {
private B b;
public C (B b) {
this.b = b;
}
public boolean isLargerThanTen() {
return b.getSomeCalculation() > 10;
}
}
Now suppose you're testing C.isLargerThanTen(). Without mocking, you'll have to know how exactly to construct B so that its getSomeCalculation() returns such a number. E.g.:
A a = new A();
a.setSomething(1);
a.setSomethingElse(2);
B b = new B(a);
b.setAnotherThing(999);
b.setYetAnotherThing(888);
C c = new C(b);
assertTrue(c.isLargerThanTen());
This is problematic on two fronts - first, it's cumbersome. Second, it makes you know the internal workings of B (and in this case, A, which B depends on too). If B were to change its implementation, C's test would break, even though there's nothing wrong with C, just with the (bad) way its test is set up.
Instead, if you use mocking, you could just simulate the only part of the behavior you care about, without the hassle of understanding the internal implementation details of B:
B b = Mockito.mock(B.class);
Mockito.when(b.getSomeCalculation()).thenReturn(11);
C c = new C(b);
assertTrue(c.isLargerThanTen());
This sounds like homework, but the advantage to using a mocking framework like Mockito is that it allows you to completely separate the functionality of each component when performing tests. That is, you only need to test the interface presented by A and the possible scenarios (various inputs, etc) because you can control what the mocked B and C classes do.
For example, if you need to test error handling in A you can simply have your mock B object throw an exception without having to actually generate the error condition in B that would have otherwise triggered the exception.
The short answer is because it gives you a greater degree of control over the class under test (and that class's dependencies) and allows you to simulate real-world conditions that would otherwise take a lot more code to generate.

Categories