How to create mockito test for Manual dependency injection - java

I am creating manual dependency injection using java. I am trying to create Mockito test for the same.
As I am new to Mockito and I have done only for framework based before. So need your help on the below
//All Business logic holder class. It does not have any new operator. Even, it does not have any knowledge about the concrete implementations
class MyClass {
private MyProto a;
private B b;
private C c;
MyClass(MyProtoImpl a, B b, C c) {
//Only Assignment
this.a = a;
this.b = b;
this.c = c;
}
//Application Logic
public void doSomething() {
a.startClient(c);
//Do B specific thing
//Do C specific thing
}
}
//The Factory. All the new operators should be placed in this factory class and wiring related objects here.
class MyFactory {
public MyClass createMyClass() {
return new MyClass(new AImpl(), new BImpl(), new CImpl());
}
}
class Main {
public static void main(String args[]) {
MyClass mc = new MyFactory().createMyClass();
mc.doSomething();
}
}
So at last I need to achieve two things.
To Test MyFactory class and MyClass
To Test MyProtoImpl class. So in this way I can get the entire codecoverage. So not only MyProtoImpl need to be covered with Junit Mockito MyFactory and MyClass also need to be covered

Normally you want to create mocks of your dependencies. From the comments it seems that you want to test the classes in separation, hence I would suggest "unit testing" the modules. I will walk you through the testing of MyClass.
class MyTestClass {
// First you want to create mocks of your dependencies
#Mock
MyProto a;
#Mock
B b;
#Mock
C c;
// At this point Mockito creates mocks of your classes.
// Calling any method on the mocks (c.doSomething()) would return null if the
// method had a return type.
#Test
void myFirstTest(){
// 1. Configure mocks for the tests
// here you configure the mock's returned values (if there are any).
given(a.someMethod()).willReturn(false);
// 2. Create the SUT (Software Under Test) Here you manually create the class
// using the mocks.
MyClass myClass = new MyClass(a, b, c);
// 3. Do the test on the service
// I have assumed that myClass's doSomething simply returns a.someMethod()'s returned value
boolean result = myClass.doSomething();
// 4. Assert
assertTrue(result);
// Alternatively you can simply do:
assertTrue(myClass.doSomething());
}
}
If your classes contain void methods, you can test whether the methods have been called with the correct arguments:
verify(a).someMethod(someParameter);
That's pretty much it for Mockito. You create mocks, you set the desired behavior, and finally you assert the result or verify that the methods have been called with the correct arguments.
However I don't think it makes that much sense to "Mockito-test" classes that are responsible for database connections and similar configuration. Mockito testing is IMHO more suited to test the service/logic layer of the application. If you had a spring project I would simply test such configuration classes (i.e. database config etc.) in a scenario, where i establish a real connection to the database.

Related

Mockito how to mock a private method [duplicate]

public class A {
public void method(boolean b){
if (b == true)
method1();
else
method2();
}
private void method1() {}
private void method2() {}
}
public class TestA {
#Test
public void testMethod() {
A a = mock(A.class);
a.method(true);
//how to test like verify(a).method1();
}
}
How to test private method is called or not, and how to test private method using mockito?
Not possible through mockito. From their wiki
Why Mockito doesn't mock private methods?
Firstly, we are not dogmatic about mocking private methods. We just
don't care about private methods because from the standpoint of
testing private methods don't exist. Here are a couple of reasons
Mockito doesn't mock private methods:
It requires hacking of classloaders that is never bullet proof and it
changes the api (you must use custom test runner, annotate the class,
etc.).
It is very easy to work around - just change the visibility of method
from private to package-protected (or protected).
It requires me to spend time implementing & maintaining it. And it
does not make sense given point #2 and a fact that it is already
implemented in different tool (powermock).
Finally... Mocking private methods is a hint that there is something
wrong with OO understanding. In OO you want objects (or roles) to
collaborate, not methods. Forget about pascal & procedural code. Think
in objects.
You can't do that with Mockito but you can use Powermock to extend Mockito and mock private methods. Powermock supports Mockito. Here's an example.
Here is a small example how to do it with powermock
public class Hello {
private Hello obj;
private Integer method1(Long id) {
return id + 10;
}
}
To test method1 use code:
Hello testObj = new Hello();
Integer result = Whitebox.invokeMethod(testObj, "method1", new Long(10L));
To set private object obj use this:
Hello testObj = new Hello();
Hello newObject = new Hello();
Whitebox.setInternalState(testObj, "obj", newObject);
While Mockito doesn't provide that capability, you can achieve the same result using Mockito + the JUnit ReflectionUtils class or the Spring ReflectionTestUtils class. Please see an example below taken from here explaining how to invoke a private method:
ReflectionTestUtils.invokeMethod(student, "saveOrUpdate", "From Unit test");
Complete examples with ReflectionTestUtils and Mockito can be found in the book Mockito for Spring.
Official documentation Spring Testing
By using reflection, private methods can be called from test classes.
In this case,
//test method will be like this ...
public class TestA {
#Test
public void testMethod() {
A a= new A();
Method privateMethod = A.class.getDeclaredMethod("method1", null);
privateMethod.setAccessible(true);
// invoke the private method for test
privateMethod.invoke(A, null);
}
}
If the private method calls any other private method, then we need to spy the object and stub the another method.The test class will be like ...
//test method will be like this ...
public class TestA {
#Test
public void testMethod() {
A a= new A();
A spyA = spy(a);
Method privateMethod = A.class.getDeclaredMethod("method1", null);
privateMethod.setAccessible(true);
doReturn("Test").when(spyA, "method2"); // if private method2 is returning string data
// invoke the private method for test
privateMethod.invoke(spyA , null);
}
}
**The approach is to combine reflection and spying the object.
**method1 and **method2 are private methods and method1 calls method2.
Think about this in terms of behaviour, not in terms of what methods there are. The method called method has a particular behaviour if b is true. It has different behaviour if b is false. This means you should write two different tests for method; one for each case. So instead of having three method-oriented tests (one for method, one for method1, one for method2, you have two behaviour-oriented tests.
Related to this (I suggested this in another SO thread recently, and got called a four-letter word as a result, so feel free to take this with a grain of salt); I find it helpful to choose test names that reflect the behaviour that I'm testing, rather than the name of the method. So don't call your tests testMethod(), testMethod1(), testMethod2() and so forth. I like names like calculatedPriceIsBasePricePlusTax() or taxIsExcludedWhenExcludeIsTrue() that indicate what behaviour I'm testing; then within each test method, test only the indicated behaviour. Most such behaviours will involve just one call to a public method, but may involve many calls to private methods.
Hope this helps.
I was able to test a private method inside using mockito using reflection.
Here is the example, tried to name it such that it makes sense
//Service containing the mock method is injected with mockObjects
#InjectMocks
private ServiceContainingPrivateMethod serviceContainingPrivateMethod;
//Using reflection to change accessibility of the private method
Class<?>[] params = new Class<?>[]{PrivateMethodParameterOne.class, PrivateMethodParameterTwo.class};
Method m = serviceContainingPrivateMethod .getClass().getDeclaredMethod("privateMethod", params);
//making private method accessible
m.setAccessible(true);
assertNotNull(m.invoke(serviceContainingPrivateMethod, privateMethodParameterOne, privateMethodParameterTwo).equals(null));
You're not suppose to test private methods. Only non-private methods needs to be tested as these should call the private methods anyway. If you "want" to test private methods, it may indicate that you need to rethink your design:
Am I using proper dependency injection?
Do I possibly needs to move the private methods into a separate class and rather test that?
Must these methods be private? ...can't they be default or protected rather?
In the above instance, the two methods that are called "randomly" may actually need to be placed in a class of their own, tested and then injected into the class above.
There is actually a way to test methods from a private member with Mockito. Let's say you have a class like this:
public class A {
private SomeOtherClass someOtherClass;
A() {
someOtherClass = new SomeOtherClass();
}
public void method(boolean b){
if (b == true)
someOtherClass.method1();
else
someOtherClass.method2();
}
}
public class SomeOtherClass {
public void method1() {}
public void method2() {}
}
If you want to test a.method will invoke a method from SomeOtherClass, you can write something like below.
#Test
public void testPrivateMemberMethodCalled() {
A a = new A();
SomeOtherClass someOtherClass = Mockito.spy(new SomeOtherClass());
ReflectionTestUtils.setField( a, "someOtherClass", someOtherClass);
a.method( true );
Mockito.verify( someOtherClass, Mockito.times( 1 ) ).method1();
}
ReflectionTestUtils.setField(); will stub the private member with something you can spy on.
I don't really understand your need to test the private method. The root problem is that your public method has void as return type, and hence you are not able to test your public method. Hence you are forced to test your private method. Is my guess correct??
A few possible solutions (AFAIK):
Mocking your private methods, but still you won't be "actually" testing your methods.
Verify the state of object used in the method. MOSTLY methods either do some processing of the input values and return an output, or change the state of the objects. Testing the objects for the desired state can also be employed.
public class A{
SomeClass classObj = null;
public void publicMethod(){
privateMethod();
}
private void privateMethod(){
classObj = new SomeClass();
}
}
[Here you can test for the private method, by checking the state change of the classObj from null to not null.]
Refactor your code a little (Hope this is not a legacy code). My funda of writing a method is that, one should always return something (a int/ a boolean). The returned value MAY or MAY NOT be used by the implementation, but it will SURELY BE used by the test
code.
public class A
{
public int method(boolean b)
{
int nReturn = 0;
if (b == true)
nReturn = method1();
else
nReturn = method2();
}
private int method1() {}
private int method2() {}
}
Put your test in the same package, but a different source folder (src/main/java vs. src/test/java) and make those methods package-private. Imo testability is more important than privacy.
In cases where the private method is not void and the return value is used as a parameter to an external dependency's method, you can mock the dependency and use an ArgumentCaptor to capture the return value.
For example:
ArgumentCaptor<ByteArrayOutputStream> csvOutputCaptor = ArgumentCaptor.forClass(ByteArrayOutputStream.class);
//Do your thing..
verify(this.awsService).uploadFile(csvOutputCaptor.capture());
....
assertEquals(csvOutputCaptor.getValue().toString(), "blabla");
Building on #aravind-yarram's answer: Not possible through mockito. From their wiki
So what's the OO way of testing private methods? Private methods with complex logic might be a sign that your class is violating the principle of single responsibility and that some of the logic should be moved to a new class.
Indeed, by extracting those private methods to public methods of more granular classes, you can unit test them without breaking the encapsulation of your original class.

Using mocks within a constructor

Is it possible to use mocks within a constructor?
Class A{
public B b = new B();
public A( String input ){
//I need to stub this method
b.someMethod( input );
}
// Class implementations
}
Unit Test:
Class ATest{
#Mock
B b;
#InjectMock
A a;
//option1:
#Before
setup(){
MockitoAnnotations.initMocks( this ); //Fails - since A isnt instantiated
a = new A();
}
//option2:
#Before
setup(){
a = new A();
MockitoAnnotations.initMocks( this ); // Fails in new A() due to method i want to stub as mocks werent initialized yet !
}
}
How can i approach this? thanks in advance.
This kind of design is hard to mock, and reveals a possible design flaw or at least weakness in your class under test. It probably calls for some kind of injection framework (i.e. Spring), so that you aren't explicitly calling the B constructor. Then your second test attempt would be spot on
If Spring is too heavy handed, there are lighter injection frameworks. Or finally, you could just pass B in as a constructor argument for A. Then you would have to use Mockito.mock(B.class) to make your B mock before passing it into the A constructor (and then you would forgo the use of the Mockito annotations).
I don't understand precisely what you are trying to do from this, but your second approach is correct. Only you need to instantiate the B class just as you did for A class. So, basically this is all you will need to do:
//option2:
#Before
setup(){
a = new A();
b = new B();
MockitoAnnotations.initMocks( this ); // Fails in new A() due to method i want to stub as mocks werent initialized yet !
}
}

Patching Java classes with a mock implementation in a unit test

I have a class A which instantiates an object from class B internally. That second class has lots of external side-effects, e.g. it uses a network connection.
public class A {
private B b;
public A() {
b = new B(); // 3rd party class that calls out externally (e.g. to a db)
}
}
I would like to unit test class A by providing a mock implementation of class B. I can easily create a mocked version of B by writing my own class or using something like Mockito and other frameworks, but how do I inject this mock implementation into class A's code?
I guess I could ask for an instance of class B in class A's constructor, but that seems ugly. No one really needs to know how class A does it's business.
Python has a "mock" library that allows you to "patch" functions at run time during a test. Does Java have something similar?
In this scenario I typically have a 2nd package (default) scope constuctor that allows you to pass a mock in for testing purposes.
public class A {
private B b;
/*
* Used by clients
*/
public A() {
this(new B());
}
/*
* Used by unit test
*
* #param b A mock implementation of B
*/
A(B b) {
this.b = b;
}
}
Check out Mockito. Ultimately, based on your design, you'll need to use reflection to get the mock instance of B into A.
This is trivial to solve with the JMockit mocking API:
public class ATest
{
#Test
public void myTest(#Mocked B mockB)
{
// Record expectations on "mockB", if needed.
new A().doSomethingUsingB();
// Verify expectations on "mockB", if applicable.
}
}

Testing Private method using mockito

public class A {
public void method(boolean b){
if (b == true)
method1();
else
method2();
}
private void method1() {}
private void method2() {}
}
public class TestA {
#Test
public void testMethod() {
A a = mock(A.class);
a.method(true);
//how to test like verify(a).method1();
}
}
How to test private method is called or not, and how to test private method using mockito?
Not possible through mockito. From their wiki
Why Mockito doesn't mock private methods?
Firstly, we are not dogmatic about mocking private methods. We just
don't care about private methods because from the standpoint of
testing private methods don't exist. Here are a couple of reasons
Mockito doesn't mock private methods:
It requires hacking of classloaders that is never bullet proof and it
changes the api (you must use custom test runner, annotate the class,
etc.).
It is very easy to work around - just change the visibility of method
from private to package-protected (or protected).
It requires me to spend time implementing & maintaining it. And it
does not make sense given point #2 and a fact that it is already
implemented in different tool (powermock).
Finally... Mocking private methods is a hint that there is something
wrong with OO understanding. In OO you want objects (or roles) to
collaborate, not methods. Forget about pascal & procedural code. Think
in objects.
You can't do that with Mockito but you can use Powermock to extend Mockito and mock private methods. Powermock supports Mockito. Here's an example.
Here is a small example how to do it with powermock
public class Hello {
private Hello obj;
private Integer method1(Long id) {
return id + 10;
}
}
To test method1 use code:
Hello testObj = new Hello();
Integer result = Whitebox.invokeMethod(testObj, "method1", new Long(10L));
To set private object obj use this:
Hello testObj = new Hello();
Hello newObject = new Hello();
Whitebox.setInternalState(testObj, "obj", newObject);
While Mockito doesn't provide that capability, you can achieve the same result using Mockito + the JUnit ReflectionUtils class or the Spring ReflectionTestUtils class. Please see an example below taken from here explaining how to invoke a private method:
ReflectionTestUtils.invokeMethod(student, "saveOrUpdate", "From Unit test");
Complete examples with ReflectionTestUtils and Mockito can be found in the book Mockito for Spring.
Official documentation Spring Testing
By using reflection, private methods can be called from test classes.
In this case,
//test method will be like this ...
public class TestA {
#Test
public void testMethod() {
A a= new A();
Method privateMethod = A.class.getDeclaredMethod("method1", null);
privateMethod.setAccessible(true);
// invoke the private method for test
privateMethod.invoke(A, null);
}
}
If the private method calls any other private method, then we need to spy the object and stub the another method.The test class will be like ...
//test method will be like this ...
public class TestA {
#Test
public void testMethod() {
A a= new A();
A spyA = spy(a);
Method privateMethod = A.class.getDeclaredMethod("method1", null);
privateMethod.setAccessible(true);
doReturn("Test").when(spyA, "method2"); // if private method2 is returning string data
// invoke the private method for test
privateMethod.invoke(spyA , null);
}
}
**The approach is to combine reflection and spying the object.
**method1 and **method2 are private methods and method1 calls method2.
Think about this in terms of behaviour, not in terms of what methods there are. The method called method has a particular behaviour if b is true. It has different behaviour if b is false. This means you should write two different tests for method; one for each case. So instead of having three method-oriented tests (one for method, one for method1, one for method2, you have two behaviour-oriented tests.
Related to this (I suggested this in another SO thread recently, and got called a four-letter word as a result, so feel free to take this with a grain of salt); I find it helpful to choose test names that reflect the behaviour that I'm testing, rather than the name of the method. So don't call your tests testMethod(), testMethod1(), testMethod2() and so forth. I like names like calculatedPriceIsBasePricePlusTax() or taxIsExcludedWhenExcludeIsTrue() that indicate what behaviour I'm testing; then within each test method, test only the indicated behaviour. Most such behaviours will involve just one call to a public method, but may involve many calls to private methods.
Hope this helps.
I was able to test a private method inside using mockito using reflection.
Here is the example, tried to name it such that it makes sense
//Service containing the mock method is injected with mockObjects
#InjectMocks
private ServiceContainingPrivateMethod serviceContainingPrivateMethod;
//Using reflection to change accessibility of the private method
Class<?>[] params = new Class<?>[]{PrivateMethodParameterOne.class, PrivateMethodParameterTwo.class};
Method m = serviceContainingPrivateMethod .getClass().getDeclaredMethod("privateMethod", params);
//making private method accessible
m.setAccessible(true);
assertNotNull(m.invoke(serviceContainingPrivateMethod, privateMethodParameterOne, privateMethodParameterTwo).equals(null));
You're not suppose to test private methods. Only non-private methods needs to be tested as these should call the private methods anyway. If you "want" to test private methods, it may indicate that you need to rethink your design:
Am I using proper dependency injection?
Do I possibly needs to move the private methods into a separate class and rather test that?
Must these methods be private? ...can't they be default or protected rather?
In the above instance, the two methods that are called "randomly" may actually need to be placed in a class of their own, tested and then injected into the class above.
There is actually a way to test methods from a private member with Mockito. Let's say you have a class like this:
public class A {
private SomeOtherClass someOtherClass;
A() {
someOtherClass = new SomeOtherClass();
}
public void method(boolean b){
if (b == true)
someOtherClass.method1();
else
someOtherClass.method2();
}
}
public class SomeOtherClass {
public void method1() {}
public void method2() {}
}
If you want to test a.method will invoke a method from SomeOtherClass, you can write something like below.
#Test
public void testPrivateMemberMethodCalled() {
A a = new A();
SomeOtherClass someOtherClass = Mockito.spy(new SomeOtherClass());
ReflectionTestUtils.setField( a, "someOtherClass", someOtherClass);
a.method( true );
Mockito.verify( someOtherClass, Mockito.times( 1 ) ).method1();
}
ReflectionTestUtils.setField(); will stub the private member with something you can spy on.
I don't really understand your need to test the private method. The root problem is that your public method has void as return type, and hence you are not able to test your public method. Hence you are forced to test your private method. Is my guess correct??
A few possible solutions (AFAIK):
Mocking your private methods, but still you won't be "actually" testing your methods.
Verify the state of object used in the method. MOSTLY methods either do some processing of the input values and return an output, or change the state of the objects. Testing the objects for the desired state can also be employed.
public class A{
SomeClass classObj = null;
public void publicMethod(){
privateMethod();
}
private void privateMethod(){
classObj = new SomeClass();
}
}
[Here you can test for the private method, by checking the state change of the classObj from null to not null.]
Refactor your code a little (Hope this is not a legacy code). My funda of writing a method is that, one should always return something (a int/ a boolean). The returned value MAY or MAY NOT be used by the implementation, but it will SURELY BE used by the test
code.
public class A
{
public int method(boolean b)
{
int nReturn = 0;
if (b == true)
nReturn = method1();
else
nReturn = method2();
}
private int method1() {}
private int method2() {}
}
Put your test in the same package, but a different source folder (src/main/java vs. src/test/java) and make those methods package-private. Imo testability is more important than privacy.
In cases where the private method is not void and the return value is used as a parameter to an external dependency's method, you can mock the dependency and use an ArgumentCaptor to capture the return value.
For example:
ArgumentCaptor<ByteArrayOutputStream> csvOutputCaptor = ArgumentCaptor.forClass(ByteArrayOutputStream.class);
//Do your thing..
verify(this.awsService).uploadFile(csvOutputCaptor.capture());
....
assertEquals(csvOutputCaptor.getValue().toString(), "blabla");
Building on #aravind-yarram's answer: Not possible through mockito. From their wiki
So what's the OO way of testing private methods? Private methods with complex logic might be a sign that your class is violating the principle of single responsibility and that some of the logic should be moved to a new class.
Indeed, by extracting those private methods to public methods of more granular classes, you can unit test them without breaking the encapsulation of your original class.

I need to make a variable accessible to the whole program in Java

So my problem is this. I have a class called Globals that contains all the variables I need all over the program. It works fine for things like strings, integers and other things that you can use the = operation on. For example:
public class Globals {
public static int globalInteger = 23;
public static String globalString = "Hello, dude.";
public static UserProfile globalUserProfile;
}
Somewhere in the project, I access them using these:
Globals.globalInteger += 17;
Globals.globalString = "Why, hello there!";
However, I am trying to make a class that I wrote myself global (UserProfiles.class). This class does not use the = operation, hence, it is always null when I access it from somewhere else and I get java.lang.nullPointerException. For example if I do this (newProfile(String) is a method inside UserProfiles.class):
Globals.globalUserProfile.newProfile(profileName);
I get java.lang.NullPointerException. How can I make my UserProfile.class variable accessible all throughout the project? Thanks in advance.
Write a so called factory class which builds your whole project in one step.
Example:
// a class which store configuration parameters - must be instanstiable!
public class Configuration {
public Configuration() {
// get configuration from Properties file, Resource Bundle etc.
}
}
public class A {
private Configuration configuration;
public A(Configuration configuration) {
this.configuration = configuration;
}
}
public class B {
private Configuration configuration;
private A a;
public B(A a, Configuration configuration) {
this.a = a;
this.configuration = configuration;
}
}
public class C {
private Configuration configuration;
private B b;
public C(B b, Configuration configuration) {
this.b = b;
this.configuration = configuration;
}
}
Here you have 3 classes and one configuration class. All of them are dependent on the configuration class, C is dependent on B and B is dependent on A.
As you can see, the dependencies are reflected by the constructor parameters, which is good because dependencies are explicit (that means, you now which dependencies are needed without having too look at the source code).
But, how do you build this object graph? Well, by using a factory class (here, it's even a static factory):
public class ApplicationFactory {
// prevents instantiation
private ApplicationFactory() {};
public static C buildApplicationGraph() {
// first, build the leaf objects (objects without other dependencies), here
// Configuration
Configuration configuration = new Configuration();
// now, start injecting the dependencies needed
// a only need a Configuration object
A a = new A(configuration);
// B needs a Configuration and an A object
B b = new B(a, configuration);
// we're done here
return new C(b, configuration);
}
}
As you can see, you are building the object graph bottom up. All dependencies are explicit, and you are seperating the construction process from the business logic.
What we have done here is constructor dependency injection, i.e. we passed in the dependencies every class needs via the constructor. And for creating the objects needed, we wrote a factory.
In the end, we have lightweight classes (no construction work here), explicit dependencies (which you don't have using a Singleton), and maximum flexibility (the factory could even return a subclass of C).
EDIT
One further advantage is that you're able to test you classes in isolation, as you could easily mock the parameters (e.g. by passing in subclasses of the parameters).
Try Singleton design pattern.
http://en.wikipedia.org/wiki/Singleton_pattern
Examples of GoF Design Patterns in Java's core libraries
You can instantiate your class by default in your Globals class :
public static UserProfile globalUserProfile = new UserProfile();
or you have to declare a factory method inside of UserProfile class.

Categories