How to test java class having initialisation in constructor - java

I have a java class whose constructor looks like this
private SomeManager someManager;
public MyService() {
this.someManager = ManagerHandler.getDefault();
}
The issue is that while testing ManagerHandler is not initialised so I am not able to create new object of this class to test its method. I am using mockito for testing. I am not able to understand How to mock a parameter which I am not passing in the constructor.
Is there anyway I can mock someManager using PowerMock?

You can use InjectMocks annotation. See below example:
MyService class:
public class MyService {
ManagerHandler someManager;
public MyService() {
this.someManager = ManagerHandler.getDefault();
}
// other methods
public String greetUser(String user) {
return someManager.sayHello(user) + ", Good Morning!";
}
}
ManagerHandler class:
public class ManagerHandler {
public static ManagerHandler getDefault() {
return new ManagerHandler();
}
public String sayHello(String userName) {
return "Hello " + userName;
}
}
TestClass:
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
#RunWith(MockitoJUnitRunner.class)
public class TestClass {
#Mock
ManagerHandler someManager;
#InjectMocks
MyService myService = new MyService();
#Test
public void test() {
//mock methods of ManagerHandler
Mockito.when(someManager.sayHello("Alice")).thenReturn("Hello Alice");
assertEquals("Hello Alice, Good Morning!", myService.greetUser("Alice"));
}
}

Related

Spy a class without PowerMock

I don't want to use powermock anymore. Because junit5 started mocking static classes. So i am trying to get rid of powermock methods.
While i was using PowerMock, i could easily spy a class that has a private constructor, and then i was calling the static methods.
This is a part of my code ( When i was using PowerMock )
#RunWith(PowerMockRunner.class)
#PrepareForTest(MessageValidationUtils.class)
public class MessageValidationServiceTest {
#Mock
private CheckpointCustomerService checkpointCustomerService;
#Mock
private ProductClientService productClientService;
#Before
public void setUp() {
MockitoAnnotations.openMocks(this);
PowerMockito.spy(MessageValidationUtils.class);
}
After i make a spy object of MessageValidationUtils.class, i was testing this:
when(MessageValidationUtils.validateTelegramKeyMap(messageProcessDto.getMessageMessageType(),
messageProcessDto.getMessageKeyValueMap())).thenAnswer((Answer<Boolean>) invocation -> true);
After some research i couldn't find anything related to spy a class that has a private constructor and static methods.
During mockStatic definition in Mockito you can specify setting to perform real execution by default Mockito.withSettings().defaultAnswer(Mockito.CALLS_REAL_METHODS). In this way, your static mock will work like Spy.
Let's create simple Utils class for testing.
public class Utils {
public static String method1() {
return "Original mehtod1() value";
}
public static String method2() {
return "Original mehtod2() value";
}
public static String method3() {
return method2();
}
}
Make mock for method2 and perform real execution of method1 and method3
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
public class SpyStaticTest {
#Test
public void spy_static_test() {
try (MockedStatic<Utils> utilities = Mockito.mockStatic(Utils.class, Mockito.withSettings().defaultAnswer(Mockito.CALLS_REAL_METHODS))) {
utilities.when(Utils::method2).thenReturn("static mock");
Assertions.assertEquals(Utils.method1(), "Original mehtod1() value");
Assertions.assertEquals(Utils.method2(), "static mock");
Assertions.assertEquals(Utils.method3(), "static mock");
}
}
}
Example for your class:
#Test
public void test() {
try (MockedStatic<MessageValidationUtils> utilities = Mockito.mockStatic(MessageValidationUtils.class, Mockito.withSettings().defaultAnswer(Mockito.CALLS_REAL_METHODS))) {
utilities.when(() -> MessageValidationUtils.validateTelegramKeyMap(messageProcessDto.getMessageMessageType(),
messageProcessDto.getMessageKeyValueMap())).thenAnswer((Answer<Boolean>) invocation -> true);
//perform testing of your service which uses MessageValidationUtils
}
}
UPDATE:
Example to use mockStatic in #BeforeEach
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
public class SpyStaticTest {
MockedStatic<Utils> utilities;
#BeforeEach
public void setUp() {
utilities = Mockito.mockStatic(Utils.class, Mockito.withSettings().defaultAnswer(Mockito.CALLS_REAL_METHODS));
}
#Test
public void spy_static_test1() {
utilities.when(Utils::method2).thenReturn("static mock");
Assertions.assertEquals(Utils.method1(), "Original mehtod1() value");
Assertions.assertEquals(Utils.method2(), "static mock");
Assertions.assertEquals(Utils.method3(), "static mock");
}
#Test
public void spy_static_test2() {
utilities.when(Utils::method1).thenReturn("static mock");
Assertions.assertEquals(Utils.method1(), "static mock");
Assertions.assertEquals(Utils.method2(), "Original mehtod2() value");
Assertions.assertEquals(Utils.method3(), "Original mehtod2() value");
}
#AfterEach
public void afterTest() {
utilities.close();
}
}
UPDATE:
Mockito does not provide method for static Spy creation, but you can define own utils and implemet spy static definition there.
import org.mockito.MockedStatic;
import org.mockito.Mockito;
public class MockitoUtils {
public static <T> MockedStatic<T> spyStatic(Class<T> classToMock) {
return Mockito.mockStatic(classToMock, Mockito.withSettings().defaultAnswer(Mockito.CALLS_REAL_METHODS));
}
}
In this way your tests will look more clear:
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import static com.test.MockitoUtils.spyStatic;
public class SpyStaticTest {
MockedStatic<Utils> utilsSpy;
#BeforeEach
public void setUp() {
utilsSpy = spyStatic(Utils.class);
}
#Test
public void spy_static_test1() {
utilsSpy.when(Utils::method2).thenReturn("static mock");
Assertions.assertEquals(Utils.method1(), "Original mehtod1() value");
Assertions.assertEquals(Utils.method2(), "static mock");
Assertions.assertEquals(Utils.method3(), "static mock");
}
#Test
public void spy_static_test2() {
utilsSpy.when(Utils::method1).thenReturn("static mock");
Assertions.assertEquals(Utils.method1(), "static mock");
Assertions.assertEquals(Utils.method2(), "Original mehtod2() value");
Assertions.assertEquals(Utils.method3(), "Original mehtod2() value");
}
#AfterEach
public void afterTest() {
utilsSpy.close();
}
}

Mockito not matching arguments when stubbed with functional interface

I am having trouble mocking a service dependency that accepts a functional interface in a method. I have simplified the problem to the follow test application. Mockito is not matching on the passed in lambda method reference. I have tried various ways of passing in a reference to the stubbing.
package com.example.test;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.function.Function;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;
#FunctionalInterface
interface MyCallback<T> extends Function<String, T> {
T apply(String s);
}
interface MyDependency {
<T> T submit(String id, MyCallback<T> myCallback);
}
class MyService {
private final MyDependency myDependency;
MyService(MyDependency myDependency) {
this.myDependency = myDependency;
}
String run() {
MyCallback<String> myCallback = getStringMyCallback();
return myDependency.submit("myId", myCallback);
}
public MyCallback<String> getStringMyCallback() {
return s -> "hello " + s;
}
}
#ExtendWith(MockitoExtension.class)
class TestUtil {
#Mock
private MyDependency myDependency;
#InjectMocks
private MyService myService;
#Test
void test() {
MyCallback<String> myCallback = myService.getStringMyCallback();
when(myDependency.submit("id", myCallback)).thenReturn("world");
String value = myService.run();
assertThat(value).isEqualTo("world");
}
}
The desired outcome is to pass a method lambda to the myDependency and stub different results. In this code the contents of 'value' is null.

Change value of guice instance on runtime

I´m using google guice to inject this class example
class A {
String a;
}
Then is injected in my class B
class B {
#Inject A aInstance;
public void checkValue(){
System.out.println(aInstance.a);
}
}
Maybe using aspectJ, but what I would like is, that one test of mine, would get this A instance and would set the "a" string as "foo", before execute the test that cover the B class, so when the B class invoke checkValue this one would print "foo"
You mention the word test in your question - if you are writing a jUnit test for B you could perform the injection in an #Before clause, as demonstrated here.
private Injector injector;
#Before
public void init() throws Exception {
injector = Guice.createInjector(new AbstractModule() {
#Override
protected void configure() {
bind(A.class).to(MockedInstanceOfAWithValueFoo.class);
}
});
}
You could also call
bind(A.class).toInstance(new MockedInstanceOfAWithValueFoo());
If we assume that A has a constructor by which we can define A.a, the mocked instance could look like this:
public class MockedInstanceOfAWithValueFoo extends A{
public MockedInstanceOfAWithValueFoo() {
super("foo");
}
}
Again, you could make your mocked class accept the value of A.a through a constructor to make the creation of B (and the associated value of A.a) more dynamic.
With Mockito:
import static org.junit.Assert.assertNotNull;
import static org.mockito.Mockito.when;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
public class MyTest {
#Mock
A mockA;
#InjectMocks
B mockB;
#Before
public void init() {
MockitoAnnotations.initMocks(this);
mockA.a = "Foo";
//when(mockA.getA()).thenReturn("Foo"); //if you use getter
}
#Test
public void myTest() {
assertNotNull(mockA);
assertNotNull(mockA.a);
assertNotNull(mockB);
assertNotNull(mockB.ainstance);
mockB.checkValue();
}
}

Mocking method from protected abstract method

Here's my problem in detail.
Setup:
I have class A that has a private member variable of class B.
A method(method1) in class A calls a non-static method(method2)
in class B.
Class B actually inherits method2 from a protected abstract class C and does not override it.
Problem:
I'm writing a test for class A.
In the test I'm mocking the call to method2.
Sample Code:
B b = Mockito.mock(B.class);
A a = new A(b);
Mockito.when(b.method2()).thenReturn(MY_LIST);
Now when I call method1(which in turn calls method2), I get a
NullPointerException.
Sample Code:
a.method1();
I'm assuming that this call is completely independent of the implementation of method2 since I'm mocking it. Is that wrong ? If not, what am I doing wrong ?
PS: class C is protected and Class A is in a different package from class B and C.
I see that you are using Mockito in your test. I have recently used it on a project and I did a test project with the following.
First a service (A) with uses another class (B).
public class Service {
private NonStaticClass nonStatic;
public NonStaticClass getNonStatic() {
return nonStatic;
}
public void setNonStatic(NonStaticClass nonStatic) {
this.nonStatic = nonStatic;
}
public int useStaticService () {
return 2*StaticClass.staticMethod();
}
public Integer getLastUse () {
return this.nonStatic.getLastUse();
}
}
Then here is the (B) class:
public class NonStaticClass {
private Integer lastUse = new Integer(0);
public Integer getLastUse() {
return lastUse++;
}
}
In order to test everithing is working i created a test for it.
import static org.mockito.Mockito.when;
import junit.framework.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
#RunWith(MockitoJUnitRunner.class)
public class TestNonStaticMock {
private final Integer staticMethodOutput = 10;
#Mock
NonStaticClass mock = new NonStaticClass();
#InjectMocks
Service service = new Service();
#Before
public void before () {
setMock();
}
private void setMock() {
when(mock.getLastUse()).thenReturn(staticMethodOutput);
}
#Test
public void mockNonStaticMethod () {
Integer result = service.getLastUse();
System.out.println(result.toString());
Assert.assertEquals(staticMethodOutput, result);
}
}
Hope it can be usefull.

JSF Backing Bean Unit Test

I have a backing bean called e.g. PeopleListBean. Purpose is simple: return a list of people from a repository.
public class PeopleListBean {
#Autowired
private PersonRepository personRepository;
private List<Person> people;
#PostConstruct
private void initializeBean() {
this.people = loadPeople();
}
public List<User> getPeople() {
return this.people;
}
private List<Person> loadPeople() {
return personRepository.getPeople();
}
}
I want to create a unit test for this bean, using Junit and Mockito.
Example test class below:
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.example.PersonRepository;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:/test-application-context.xml" })
public class PeopleListBeanTest {
#Autowired
private PeopleListBean peopleListBean;
#Autowired
private PersonRepository mockPersonRepository;
#Before
public void init() {
reset(mockPersonRepository);
}
#Test
public void canListPeople() {
List<Person> people = getDummyList();
when(mockPersonRepository.getPeople().thenReturn(people);
assertTrue(peopleListBean.getPeople().size() == people.size());
}
}
My issue is, when/how to mock the repository since the loading takes place in the initializeBean method (#PostConstruct). So after the class is constructed, the "getPeople" method is called before I can actually mock the method resulting in an assertion mismatch.
I'd really appreciate some help/guidance!
Use JUnit's #BeforeClass annotation
Your code would therefore look as follows:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:/test-application-context.xml" })
public class PeopleListBeanTest {
#Autowired
private PeopleListBean peopleListBean;
#Autowired
private PersonRepository mockPersonRepository;
#BeforeClass
public static void initialise() {
}
// .
// .
// .
}

Categories