SpringMVC Mockito Mocking values of class within class - spring

I am trying to use mockito to mock the return value of method3() in class3 when i run the method try() in class1 from the testclass. I have restriction as to not being able to make any edition to the codes that i have. So, i cannot add in constructors to make the mock as per some solutions that i have seen given on the internet. I am using MockMVC with WebApplicationContextSetup. Please guide me if it is possible to mock the value of method3() only using mockito and if it is not possible what is the other solution that i can use to mock the value?
class1
{
Class2 c2 = new Class2();
public String try()
{
Something temp1 = c2.method1();
}
}
class2
{
Class3 c3 = new Class3();
public String method1()
{
return c3.method3();
}
}
class3
{
//Will like to mock the return value of this method
public String method3()
{
return "asd";
}
}
testclass
{
class1 c1 = new class1();
c1.try();
}
Thanks Alot :D

Regarding your code, it looks you need to mock a static method :
return Class3.method3();
Or not
public String method3()
Please precise because the answer will be different depending your need to mock static method or not.

For this you need to Spy your class2.
import org.junit.Before;
import org.junit.Test;
import org.mockito.*;
import static org.junit.Assert.assertEquals;
public class TestClass {
#InjectMocks
private Class1 class1 = new Class1();
#InjectMocks #Spy
private Class2 class2 = new Class2();
#Mock
private Class3 class3;
#Before
public void init() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testWithMock() {
Mockito.when(class3.method3()).thenReturn("mocked");
assertEquals("mocked", class1.doTry());
}
}

Related

Is it possible to invoke mocked object's method in constructor?

I have, for example, these classes with Spring Boot. I try to do a REST API without a database and wieh files as data. The data files are like this:
{
"persons": [
{ "firstName":"John", "lastName":"Boyd", "address":"1509 Culver St", "city":"Culver", "zip":"97451", "phone":"841-874-6512", "email":"jaboyd#email.com" },
{ "firstName":"Jacob", "lastName":"Boyd", "address":"1509 Culver St", "city":"Culver", "zip":"97451", "phone":"841-874-6513", "email":"drk#email.com" }
] }
#Repository
public class PersonRepository {
private List<Person> persons;
private DataLoaderService loaderService;
#Autowired
public PersonRepository(DataLoaderService loaderService){
persons= loaderService.convertJsonToPojo("Persons",Person.class);
}
public List<Person> getAll(){
return persons;
}
}
#Service
public class DataLoaderService{
private JsonFileService jsonFileService;
private ObjectMapper mapper
#Autowired
public DataLoaderService(JsonFileService jsonFileService,ObjectMapper mapper){
this.JsonFileService =jsonFileService;
this.mapper=mapper;
}
public <T> List<T> convertJsonToPojo (String nodeName,Class <T>
classOfT){
}
}
So, I have a file. How can I read to transform to a list of Pojo?
When I want to mock the test method getAll(), my list size is 0. The mock doesn't give me values because I think the problem is that I initialized the value in the constructor. Here is my test:
#ExtendWith(MockitoExtension.class)
public class PersonRepositoryTest {
PersonRepository repository;
#Mock
private DataLoaderService loaderService;
#BeforeEach
public void setUp() {
repository = new PersonRepository(loaderService);
}
#Test
public void getAllPersonnesInConstructor() {
List<Person> mockedList = Arrays.asList(
new Person("Paul","Moes","1", "7777", "adresse tour", "Chicago", "pauln#gmail.com"),
new Person("Eleson","Moc","2", "77777", "ddkdkd", "New York", "eleson#gmail.com")
);
doReturn(mockedList).when(loaderService).convertJsonToPojo("persons",Person.class);
List<Person> persons = repository.getAll();
assertEquals(2,persons.size(),"Expected list size is 2");
assertEquals(persons,mockedList);
}
If i use #Spy, I have an error.
When I use method getAll() without initializing the variable persons in the constructor but in the method getAll, it is OK, like this:
public List<Person> getAll(){
this.persons=this.dataLoaderService.convertJsonToPojo("persons", Person.class);
log.debug("persons getALL repository" + persons);
return this.persons;
}
What can I do to test it?
Test a method which initializes a value in the constructor.

Inversion of control based on properties file

Below is my interface :-
interface Student {
findById();
}
Below are my 2 implementations of interface :-
class Matriculation implements Student {
findById(){
//implementation
}
}
class Graduation implements Student {
findById(){
//implementation
}
}
application.properties
graduation=true
Calling class :-
class Test {
#Autowired
Student student ;
method(){
student.findById();
}
}
If graduation is true i want to call Graduation class findById else i want to call Matriculation findById method .How can i achieve this in SpringBoot?
you can use the #ConditionalOnProperty annotation. Like this:
#ConditionalOnProperty(name = "graduation", havingValue = "true")
#Service
public class Graduation implements Student
{
#Override
public String findById()
{
return "Graduation";
}
}
correctly indicated in comments, here is a possible implementation.
class Test {
#Autowired
Matriculation matriculationStudent ;
#Autowired
Graduation graduationStudent;
#Value("${graduation}")
private boolean graduation;
void method(){
if (graduation) {
graduationStudent.findById();
} else {
matriculationStudent.findById();
}
}
}
You're gonna create a Spring Component like this:
#Component
public class StudentFactory {
#Autowired
private Matriculation matriculation;
#Autowired
private Graduation graduation;
#Value("${graduation}")
private boolean graduationValue;
public Student getImplementation() {
if (graduationValue) {
return graduation;
} else {
return matriculation;
}
}
}
and then you just inject the factory in the Test class and call getImplementation method

Spring boot cache not working in #PostConstruct

I'm building a "class cache", with classes I want to call later.
The main goal is that I don't want scan the context every time that a class instance is needed.
# Model / Repository classes
#Getter
#RequiredArgsConstructor
public class Block implements Serializable {
private final String className;
private final Set<String> classCandidates = new HashSet<>();
public boolean addCandidate(final String classCandidate) {
return this.classCandidates.add(classCandidate);
}
}
#Slf4j
#Component
#CacheConfig(cacheNames = ConstantsCache.CACHE_BLOCK)
public class BlockRepository {
#Cacheable(key = "#className")
public Block findByInputClass(final String className) {
log.info("---> Loading classes for class '{}'", className);
val block = new Block(className);
findCandidates(block);
return block;
}
}
First to evaluate the cache, I've put the cache method #Autowired in a #RestController, wich works fine. The cache is populated when I call the rest method.
#RestController
public class Controller {
#Autowired
BlockRepository blockRepository;
#RequestMapping("/findByInputClass")
public Block findByInputClass(#RequestParam("className") final String className) {
return blockRepository.findByInputClass(className);
}
}
After doing that, I've moved the #Autowired object to a #Service, creating a method to self-populate the cache. But this does not work. The cache is not populated when the #PostConstructor method is called.
#Slf4j
#Component
public class BlockCacheService {
#Autowired
BlockRepository blockRepository;
#PostConstruct
private void postConstruct() {
log.info("*** {} PostConstruct called.", this.getClass().getTypeName());
val block = blockRepository.findByInputClass(ConstantsGenerics.BLOCK_PARENT_CLASS);
final Set<String> inputClasses = getInputFromCandidates(block.getClassCandidates());
appendClassesToCache(inputClasses);
}
private void appendClassesToCache(final Set<String> inputClasses) {
for (val inputClass : inputClasses) {
blockRepository.findByInputClass(inputClass);
}
}
}
How can I properly populate the cache using a service or component, that must start with the application.
Thanks in advance.
EDIT:
I've found a possible solution here: https://stackoverflow.com/a/28311225/1703546
Than I've changed the #Service code to put the cache manually instead of use the #Cacheable magic abstraction.
The class now is like this.
#Slf4j
#Component
public class BlockCacheService {
#Autowired
CacheManager cacheManager;
#Autowired
BlockRepository blockRepository;
#PostConstruct
private void postConstruct() {
log.info("*** {} PostConstruct called.", this.getClass().getTypeName());
val block = blockRepository.findByInputClass(ConstantsGenerics.BLOCK_PARENT_CLASS);
final Set<String> inputClasses = getInputFromCandidates(block.getClassCandidates());
appendClassesToCache(inputClasses);
}
private void appendClassesToCache(final Set<String> inputClasses) {
for (val inputClass : inputClasses) {
val block = blockRepository.findByInputClass(inputClass);
cacheManager.getCache(ConstantsCache.CACHE_BLOCK).put(block.getClassName(), block);
}
}
}
Now the cache is populated correctly, but the question is, this is the best solution?
Thanks.
You can't use an aspect in #PostConstruct as it may not have been created yet (and that is documented by the way).
One possible way to make that work is to implement SmartInitializingBean instead as it gives a callback when all singletons have been fully initialized (including their aspect. Changing that on your original service should work.
Having said that, this code of yours has an impact on the startup time. Why don't you let your cache to be filled lazily instead?

PowerMockito verifyNew and verifyPrivate are mutually exclusive?

I have a class like this
#Component
public class TestClass {
public void testMethod(){
FinalClass f = new FinalClass("string");
somePrivateMethod(f.getSomeString());
}
private void somePrivateMethod(String s){
}
}
As you can see it has a public method and private method. In public method it is instantiating an instance of FinalClass, which is a class in some third party library and it is final. Lets say it is like this
public final class FinalClass {
private final String someString;
public FinalClass(final String s) {
someString = s;
}
public String getSomeString() {
return someString;
}
}
And Now I am writing unit test for my test class. Since I have to verify final classes and private methods, I am using powermockito. And this is how my test class looks like
#RunWith(PowerMockRunner.class)
#PrepareForTest({TestClass.class, FinalClass.class})
public class TestClassTest {
private TestClass testClass;
private FinalClass finalClass;
#Before
public void setUp() {
finalClass = PowerMockito.mock(FinalClass.class);
testClass = spy(new TestClass());
}
#Test
public void testSomething() throws Exception {
whenNew(FinalClass.class).withAnyArguments().thenReturn(finalClass);
testClass.testMethod();
verifyNew(FinalClass.class);
//verifyPrivate(testClass).invoke("testMethod");
}
}
It works fine. But the problem is the last two statements verifyNew and verifyPrivate are working mutually exclusively. I mean when I comment one of those(doesn't matter which), the test passes. But when both are enabled, the test fails
Does anyone have any idea why this is happening?

Unitest by using mockito(one class is dependent with other scenario)

Hi I am very new to mocking framework. Can any one please help me to write a junit by using any mocking framework. Below is my requirement
I wanted to write a unitest for getListOfEmp method by using mock with expected value.
Note Here I am facing difficulty to mock EmpValue class to get the accurate value in ServiceClass
public class ServiceClass {
public Employe getListOfEmp(List<String> criteria) {
Employe emp = new Employe();
EmpValue empValue = new EmpValue();
if (criteria.contains("IT")) {
emp.setEid(empValue.getIt());
}
if (criteria.contains("SALES")) {
emp.setEid(empValue.getSales());
}
if (criteria.contains("SERVICE")) {
emp.setEid(empValue.getService());
}
return emp;
}
}
public class EmpValue {
private String it = "IT-1001";
private String service = "SERVICE-1001";
private String sales = "SALES-1001";
public String getIt() {
return it;
}
public String getService() {
return service;
}
public String getSales() {
return sales;
}
}
First I will do some changes to the code to make it testable.
1: EmplValue object should be passed to the method by the client or should be an instance variable in your Service class. Here I am using it as an instance variable, so that client can set it.
public class ServiceClass {
private EmpValue empValue;
public ServiceClass(EmpValue empValue){
this.empValue = empValue;
}
public Employe getListOfEmp(List<String> criteria) {
Employe emp = new Employe();
if (criteria.contains("IT")) {
emp.setEid(empValue.getIt());
}
if (criteria.contains("SALES")) {
emp.setEid(empValue.getSales());
}
if (criteria.contains("SERVICE")) {
emp.setEid(empValue.getService());
}
return emp;
}
}
I am using Mockito and JUnit to write unit-test for this class .
import static org.mockito.Mockito.*;
import static org.junit.Assert.*;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;
#RunsWith(MockitoJunitRunner.class)
public class ServiceClassTest{
#Test
public void shouldReturnEmployeeWithEidSetWhenCriteriaIsIT(){
// Craete mock and define its behaviour
EmpValue mEmpValue = mock(EmpValue.class);
when(mEmpValue.getIt()).thenReturn("IT-1001");
// Create the object of class user test with mock agent and invoke
ServiceClass serviceClass = new ServiceClass(mEnpValue);
Employee result = serviceClass.getListOfEmp(asList("IT"));
// Verify the result as per your expectation
assertEquals("It-001", result.getEid());
}
}

Resources