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() {
}
// .
// .
// .
}
Related
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.
When I am trying to MOC the dependent classes (instance variables), it is not getting mocked for abstract class. But it is working for all other classes. Any idea how to resolve this issue. I know, I could cover this code from child classes. But I want to know whether it is possible to cover via abstract class or not. Also, I want to use Mockito to resolve it.
Currently, I am getting a NULL point exception on the following line because the mamApiDao is null & not getting mocked
OvpStatusResponse ovpStatusResponse = mamApiDao.updateOvpMetadataInMam(null, callbackMessage.getMediaId(), ovpStatus, publishMessage);
Abstract class
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qvc.qq.mamapimodel.model.mamapi.OvpStatus;
import com.qvc.qq.mamapimodel.model.mamapi.response.OvpStatusResponse;
import com.qvc.qq.mammessageprocessor.config.settings.MqMessageSettings;
import com.qvc.qq.mammessageprocessor.dao.MamApiDao;
import com.qvc.qq.mammessageprocessor.manager.ErrorMessageManager;
import com.qvc.qq.mammessageprocessor.model.CdnCallbackMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.server.ResponseStatusException;
public abstract class CallbackManager {
private final MamApiDao mamApiDao;
public CallbackManager( MamApiDao mamApiDao) {
this.mamApiDao = mamApiDao;
}
public void processCallback(CdnCallbackMessage callbackMessage, int retries, OvpStatus ovpStatus, String publishMessage) {
// some code
//mamApiDao is NULL, it is not getting mocked
OvpStatusResponse ovpStatusResponse = mamApiDao.updateOvpMetadataInMam(null, callbackMessage.getMediaId(), ovpStatus, publishMessage);
// some code
}
}
Test Class
import com.qvc.qq.mamapimodel.model.mamapi.OvpStatus;
import com.qvc.qq.mamapimodel.model.mamapi.response.OvpStatusResponse;
import com.qvc.qq.mammessageprocessor.config.settings.MqMessageSettings;
import com.qvc.qq.mammessageprocessor.dao.MamApiDao;
import com.qvc.qq.mammessageprocessor.dao.MqMessagingDao;
import com.qvc.qq.mammessageprocessor.model.CdnCallbackMessage;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.isNull;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class CallbackManagerTest {
#InjectMocks
CallbackManager callbackManager = Mockito.mock(CallbackManager.class, Mockito.CALLS_REAL_METHODS);
#Mock
MamApiDao mamApiDao;
#BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
}
#Test
public void processCallbackTest() {
when(mamApiDao.updateOvpMetadataInMam(any(), anyString(), any(), anyString())).thenReturn(new OvpStatusResponse());
callbackManager.processCallback(cdnCallbackMessage, 1, OvpStatus.ACTIVE, "published");
verify(mamApiDao, times(1)).updateOvpMetadataInMam(any(), anyString(), any(), anyString());
}
}
Enum Class
public enum OvpStatus {
SUBMITTED("SUBMITTED"),
ACTIVE("ACTIVE"),
INACTIVE("INACTIVE"),
ERROR("ERROR"),
NONE("NONE");
private String value;
private OvpStatus(String value) {
this.value = value;
}
public String getValue() {
return this.value;
}
}
Dao class
import com.qvc.qq.mamapimodel.model.mamapi.OvpStatus;
import com.qvc.qq.mamapimodel.model.mamapi.response.OvpStatusResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
#Slf4j
#Component
public class MamApiDao {
public OvpStatusResponse updateOvpMetadataInMam(String mamId, String ovpId, OvpStatus status, String publishMessage) {
OvpStatusResponse ovpStatusResponse = new OvpStatusResponse();
ovpStatusResponse.setId(1);
ovpStatusResponse.setStatus("");
return ovpStatusResponse;
}
}
Test Dependency
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
can you try like the below one?
public class CallbackManagerTest {
#InjectMocks
CallbackManager callbackManager = Mockito.mock(CallbackManager.class, Mockito.CALLS_REAL_METHODS);
#MockBean
private MamApiDao mamApiDao;
#BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
}
//do something
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"));
}
}
I want to execute a simple log on all methods of annotated class with a custom annotation. I've created the next annotation:
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
public #interface FooAnnotation {}
And it's used on a random class:
#FooAnnotation
public class Bar{
...
}
Of course my start class has #EnableAspectJAutoProxy annotation
#EnableAspectJAutoProxy
#SpringBootApplication
public class FooApplication {
public static void main(String[] args) {
SpringApplication.run(FooApplication.class, args);
}
}
In the related AspectJ I need to define a #Pointcut to execute #After on all methods of all clases that are annotated with #FooAnnotation
I tried the next AspectJ and it doesn't work
#Slf4j
#Aspect
#Component
public class FooAspectJ{
#Pointcut("within(x.y.z.FooNotify)")
private void annotatedWithin() {}
#Pointcut("#within(x.y.z.FooNotify)")
private void annotatedAtWithin() {}
#Pointcut("#annotation(x.y.z.FooNotify)")
private void annotatedAtAnnotation() {}
#After("annotatedWithin() || annotatedAtWithin() || annotatedAtAnnotation()")
private void afterAnnotation(JoinPoint joinPoint){
log.info("Executed annotated {}", joinPoint.getSignature().getName());
}
}
I see similar post about this, like
#AspectJ pointcut for all methods of a class with specific annotation and aspectj pointcut with annotation parameters, with the same result.
It should be like
#Pointcut("within(#x.y.z.FooNotify *)")
Example:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;
#FooNotify
#Repository
public class Bar {
private static final Logger logger = LoggerFactory.getLogger(Bar.class);
public String returnSomeString() {
logger.info("returnSomeString ...");
int i = returnMeAnInt();
logger.info("returnMeAnInt returned {}", i);
return "Hello";
}
public void doSomething() {
logger.info("doSomething ...");
}
private int returnMeAnInt() {
logger.info("returnMeAnInt ...");
return 4;
}
}
Aspect:
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
#Component
#Aspect
public class BarAspect {
private static final Logger logger = LoggerFactory.getLogger(BarAspect.class);
#Pointcut("within(#FooNotify *)")
public void fooNotifyPointcut() {}
#After("fooNotifyPointcut()")
public void afterAnnotation(JoinPoint jp) {
logger.info("afterAnnotation joinpoint: {}", jp.getStaticPart().getSignature());
}
}
Annotation:
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
#Retention(RUNTIME)
#Target(TYPE)
public #interface FooNotify {}
Call:
bar.returnSomeString();
bar.doSomething();
Logs:
Bar:13- returnSomeString ...
Bar:24- returnMeAnInt ...
Bar:15- returnMeAnInt returned 4
BarAspect:21- afterAnnotation joinpoint: String
com.pkg.Bar.returnSomeString()
Bar:20- doSomething ...
BarAspect:21- afterAnnotation joinpoint: void
com.pkg.Bar.doSomething()
For private methods, you have to use full aspectj.
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();
}
}