Issue mocking a class variable value in java - java

I have a class that has a private class variable initialized like
public class MyClass{
private BusinessObject businessObject = BusinessObjectGenerator.getBusinessObject();
public MyClass(){
}
public Object myMethodToTest(){
return businessObject.getObject();
}
}
Now, I'm trying to unit test myMethodToTest I want to send in a mock object in place of businessObject. I use mockito for mocking and use spy(new MyClass()) for partial mocking but having trouble with mocking the call to get businessObject.
1. Is it possible to mock the call to the businessObject? If so how?
2. How can I refactor this code to help while writing unit test. Any resources pointing towards this would be of great help.
Thanks!

To properly refactor this code you'd:
private BusinessObject businessObject;
public void setBusinessObject(BusinessObject instance) {
businessObject = instance;
}
private BusinessObject getBusinessObject() {
if (businessObject == null) {
// represents existing implementation in original code sample
businessObject = BusinessObjectGenerator.getBusinessObject();
}
return businessObject;
}
/* rest of your code */
Now you can inject your mock into the class yourself at the test site.
I'd recommend doing this using dependency injection with a framework like Guice. It will be worth your time.

Related

How to mocking the implemented methods of a class under test in Spring Boot with Mockito

I am unsure after much reading how to test the class below.
I have given a basic example...but assuming the class/implemented method could produce a more complex object (not just a String as below), how can I mock the interface so I can inject a mock in to the class to test various class behaviours?
For example, in the oversimplified below...if the length of the 'sayHello' was more than 500chars when calling the class 'getSayHelloLength()', I may want to Assert a 'HelloTooLongException' is thrown.
/**
* MyClass implements MyInterface.
*/
public class MyClass implements MyInterface {
public int getSayHelloLength() {
return sayHello().length();
}
//I want to change/Mock the return of the implemented interface.
#Override
public String sayHello() {
//Do some magic and some code an eventually return something based upon 'input'
// Magic
// More magic.
return "My Class to Test Says Hello!";
}
}
The interface:
public interface MyInterface {
String sayHello();
}
I am using JUnit5:
class MyClassTest {
#InjectMocks
private MyClass myClass;
#BeforeEach
void setUp() {
}
#Test
void getSayHelloLength() {
//Mock the interface 'myClass' implements as to test various "hellos" outputs.
}
}
Since you're not testing the interface (no code to test in there) but the implementation. There is no need to mock the interface. You don't want to mock the code you're testing in any case. You want to mock everything the code you're testing uses.
So supposed the 'Magic' part is in another class, you want to mock this one. If it isn't you might want to refactor your class until it is because then it's violating the Single-Responsibility-Principle since doing magic and saying hello seem to be very different concerns.

Mocking getInstance of a singleton using PowerMock

I have the following Singleton that returns an instance of a different class. I want to mock the method on that returned instance object. I've been reading on PowerMock mocking features for final classes and singletons but I don't know if my case falls under those or not. I appreciate some suggestion.
public final class SomeWrapper {
private MyActualObject MyActualObject;
private static final SomeWrapper instance = new SomeWrapper();
private SomeWrapper() {
// singleton
}
public static SomeWrapper getInstance() {
return instance;
}
public void setMyActualObject(MyActualObject MyActualObject) {
if(this.MyActualObject == null) {
this.MyActualObject = MyActualObject;
} else {
throw new UnsupportedOperationException("MyActualObject is already set, cannot reset.");
}
}
public MyActualObject getMyActualObject() {
return MyActualObject;
}
}
So now in my unit test, I wanna mock the following line:
when(SomeWrapper.getInstance().getMyActualObject().isActive()).thenReturn(false);
Should I mock the SomeWrapper and MyActualObject? Any code sample as guidance?
Using these Mockito & PowerMock versions:
testImplementation 'org.mockito:mockito-core:2.23.4'
testImplementation 'org.powermock:powermock-module-junit4:2.0.0-beta.5'
testImplementation 'org.powermock:powermock-api-mockito2:2.0.0-beta.5'
You are able to mock an android MainApplication singleton instance (for example) using PowerMock.mockStatic() and the when() mechanism, like this:
private MainApplication mApplication;
#NonNull
protected MainApplication getApplication() {
if (mApplication == null) {
mApplication = PowerMockito.mock(MainApplication.class);
PowerMockito.mockStatic(MainApplication.class);
PowerMockito.when(MainApplication.getInstance()).thenReturn(mApplication);
PowerMockito.when(mApplication.getBaseContext()).thenReturn(mApplication);
PowerMockito.when(mApplication.getApplicationContext()).thenReturn(mApplication);
}
return mApplication;
}
Mocking the private constructor could be tricky - you might try the approach suggested in this post, by using a substitute class in the thenReturn() call:
SO - Mocking Private Constructor
The point here is: you wrote hard-to-test code. And yes, PowerMock can help "fixing" that, but you might prefer to simply rework your production code to make it easier to test.
For example, by adding a package protected constructor like:
SomeWrapper(MyActualObject myActualObject) {
this.MyActualObject = myActualObject;
}
This would allow you to create an instance of SomeWrapper class that receives a completely valid MyActualObject instance.
In that sense: you might want to learn how to create production code that is actually testable.

How do you mock classes that are used in a service that you're trying to unit test using JUnit + Mockito

I want to write a unit test for a service that uses/depends on another class. What i'd like to do is mock the behavior of the dependent class (As opposed to an instance of that class). The service method being tested uses the dependent class internally (i.e. an instance of the dependent class isn't passed in to the method call) So for example I have a service method that I want to test:
import DependentClass;
public class Service {
public void method() {
DependentClass object = new DependentClass();
object.someMethod();
}
}
And in my unit test of Service method(), I want to mock someMethod() on the DependentClass instance instead of having it use the real one. How do I go about setting that up in the unit test?
All of the examples and tutorials i've seen show mocking object instances that are passed in to the method being tested, but I haven't seen anything showing how to mock a class as opposed to an object instance.
Is that possible with Mockito (Surely it is)?
It's easy with Powermockito framework and whenNew(...) method. Example for your test as follows:
#Test
public void testMethod() throws Exception {
DependentClass dependentClass = PowerMockito.mock(DependentClass.class);
PowerMockito.whenNew(DependentClass.class).withNoArguments().thenReturn(dependentClass);
Service service = new Service();
service.method();
}
Hope it helps
This is a problem of poor design. You can always take in the param from a package private constructor.
Your code should be doing something like this:
public class Service {
DependentClass object;
public Service(){
this.object = new DependentClass();
}
Service(DependentClass object){ // use your mock implentation here. Note this is package private only.
object = object;
}
public void method() {
object.someMethod();
}
}

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.

How to mock a private inner class

I have a spring application and I want to create a unitary test on a controller like this one. The problem is that the Wrapper class is a private inner class, so Wrapper is not understood in the test. Is it possible to mock it with Mockito without changing the controller class. I can use prepareData() to get an instance of the object, but I don't know if this could be used to mock that object.
Thanks
#Controller
public class Controller {
private class Wrapper {
private Object1 field1;
private Object2 field2;
private Object1 method1(){
...
}
private Object2 method1(){
...
}
}
#ModelAttribute("data")
public Wrapper prepareData() {
return new Wrapper ();
}
public String save(#ModelAttribute("data") Wrapper wrapper, BindingResult result, Model model){
...
}
}
So in my test I would have something like this
#Test
public void usernameEmpty(){
BindingResult result = Mockito.mock(BindingResult.class);
Model model = Mockito.mock(Model.class);
Wrapper data = //how to mock it
when(data.method1()).then(new Foo1());
when(data.method2()).then(new Foo2());
String returned = controller.save(data, result, model);
....
}
Your test is on methods, but it tests the whole class behavior. If your inner class is private then its an implementation detail. Something that the test shouldn't know. It there's a lot of behaviour in that inner-class and you want to test it independently maybe you should make it public and separate from this class.
Maybe you think: but then... it's a lot of code to test (a very big indivisible thing), can't I test something smaller? Well... yes. Test Driven Development mandates to make a minimal implementation and add more code only if you add more tests. So you start with some test and minimal implementation and evolve both of them until the tests have all the specification and the code all the implementation.
So don't worry about private inner classes. Test your class contract!

Categories