Mocking Autowired static field - spring

I am trying to mock a static Autowired Field but getting a null pointer exception in my testmethods on executing the JunitTest.
Below is my source and test class code snippet.
public class MyUtil {
private static Logger log = LoggerFactory.getLogger(MyUtil.class);
private static MyLogger myLogger;
#Autowired
private MyLogger tMyLogger;
#PostConstruct
public void init() {
ModelUtil.myLogger = tMyLogger;
}
public static String getSomething(String foo) {
if (foo != null) {
myLogger.log(foo);
}
}
MyLoggerTestClass is below:
#RunWith(SpringJUnit4ClassRunner.class)
public class MyUtilTest {
private static MyLogger myLoggerMock;
#Mock
private MyLogger tMyLoggerMock;
#PostConstruct
public void init() {
ModelUtilTest.myLoggerMock = tMyLoggerMock;
}

Related

Why is a bean created twice in test when using #PostConstruct?

I have a configuration class that uses a properties file and it works properly.
Now I want to test that code and I have to recognize that the method annotated with #PostConstruct is run twice during the test. (In debug mode I can see that the for-loop is conducted twice.)
The configuration class:
#Slf4j
#RequiredArgsConstructor
#Configuration
#ConfigurationPropertiesScan("com.foo.bar")
public class MyConfig {
private final MyProperties myProperties;
#Autowired
private GenericApplicationContext applicationContext;
#PostConstruct
void init() {
Objects.requireNonNull(myProperties, "myProperties may not be null");
for (final MyProperties.MyNestedProperty nested : myProperties.getApps()) {
log.info("xxx {} created.", nested.getName());
applicationContext.registerBean(nested.getName(), MyContributor.class, nested);
}
}
}
The used properties class:
#Slf4j
#Data
#Validated
#ConfigurationProperties(prefix = MyProperties.CONFIG_PREFIX)
public class MyProperties {
public static final String CONFIG_PREFIX = "xxx";
#Valid
#NestedConfigurationProperty
private List<MyNestedProperty> apps;
#Data
public static class MyNestedProperty {
#NotNull
#NotEmpty
private String abc;
private String xyzzy;
#NotNull
#NotEmpty
private String name;
}
}
My attempt with the test class:
#ExtendWith(SpringExtension.class)
#RequiredArgsConstructor
#ContextConfiguration(classes = MyConfigTest.MyTestConfiguration.class)
class MyConfigTest {
#MockBean
MyProperties myProperties;
ApplicationContextRunner context;
#BeforeEach
void init() {
context = new ApplicationContextRunner()
.withBean(MyProperties.class)
.withUserConfiguration(MyConfig.class)
;
}
#Test
void should_check_presence_of_myConfig() {
context.run(it -> {
assertThat(it).hasSingleBean(MyConfig.class);
});
}
// #Configuration
#SpringBootConfiguration
// #TestConfiguration
static class MyTestConfiguration {
#Bean
MyProperties myProperties() {
MyProperties myProperties = new MyProperties();
MyProperties.MyNestedProperty nested = new MyProperties.MyNestedProperty();
nested.setName("xxx");
nested.setAbc("abc");
nested.setXyz("xyz");
myProperties.setApps(List.of(nested));
return myProperties;
}
}
}
Why does this happen and how can I prevent this behaviour?

How to inject #Value properties from application.properties to #InjectMocks in springboot?

BatchService.java
#Service
public class BatchService {
#Value("#{${priority.mapping}}")
public Map<String, String> priorMap;
#Autowired
private Repo payload;
public boolean createAndAddBatches(){
for (String priority: priorMap.keySet()) {
// code
}
}
}
BatchServiceTest.java
#RunWith(PowerMockRunner.class)
public class BatchServiceTest {
#Value("#{${priority.mapping}}")
private static Map<String, String> priorMap;
#Mock
private Repo repoMock;
#InjectMocks
private BatchService batchService;
#BeforeClass
#PrepareForTest({LogManager.class})
public static void setup() {
ReflectionTestUtils.setField(BatchService.class, "priorMap", priorMap);
}
Error
java.lang.IllegalAccessError: class javax.xml.parsers.FactoryFinder (in unnamed module #0xc3cdf38) cannot access class jdk.xml.internal.SecuritySupport (in module java.xml) because module java.xml does not export jdk.xml.internal to unnamed module #0xc3cdf38
application.properties
priority.mapping = {'first':'1','second':'2','third':'3'}
is there a way to inject the hashmap from the properties file to BatchService? It throws error when I used ReflectionTestUtils.setField(BatchService.class, "priorMap", priorMap);
Don't use BatchService.class, use the instance you are testing:
#BeforeEach
public void init() throws Exception {
ReflectionTestUtils.setField(batchService, "priorMap", "value you want to inject");
}

When I call method from Test I have Always null resolte

I have test class ExecuteTest and I want to test the method returnString method who is in MyStringClass, and in returnString I call strings() from class OtherString.
This is my code:
#RunWith(MockitoJUnitRunner.class)
public class ExecuteTest {
#InjectMocks
private MyStringClass myStringClass;
#Mock
private OtherString otherString;
#Before
public void init() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testString() {
String test = myStringClass.returnString("test");
assertThat(test, equalTo(test));
}
}
#Service
public class MyStringClass {
#Autowired
private OtherString otherString;
public <T extends Object> T returnString(String key) {
return (T) otherString.strings(key);
}
}
And my test variable is always null in my test.

Unable to mock a method with Mockito and Spring

I have a class JobDelegate for which i am writing unit tests using mockito. I am unable to mock the HTTPOperations class. I have tried using setter injection from test class as well. But it does not work. Below the latest revision of the code. I tried using Power mock. but none of them was helpful. I am unable to predict which is going wrong.
Unit Test code
#ContextConfiguration(locations= "file:src/main/webapp/WEB-INF/spring-
context.xml")
#RunWith(SpringJUnit4ClassRunner.class)
//#RunWith(PowerMockRunner.class)
/#PowerMockIgnore({ "javax.xml.*", "org.xml.*", "org.w3c.*" })
//#PrepareForTest({ HTTPOperations.class})
public class JobSubmissionDelegateTest{
private static Logger LOGGER = null;
private JobDelegate jobDelegate ;
private JobManager jobImpl;
#InjectMocks
private HTTPOperations operations;
//#Rule public MockitoRule mockitoRule = MockitoJUnit.rule();
#Before
public void setupTests() {
jobDelegate = new JobDelegate();
jobManager = new DBJobManagerImpl();
operations = new HTTPOperations();
jobManager.setHttpOperations(operations);
jobSubmissionDelegate.setJobImpl(jobManager);
//HTTPOperations httpOperationsSpy =spy(HTTPOperations.class);
//doReturn("{\"response\":\"{\\\"run_id\\\":32423423}\\n\"}").when(myClassSpy).method1();
MockitoAnnotations.initMocks(this);
}
#Test
public void testExecuteJob() throws IOException {
// PowerMockito.mockStatic(HTTPOperations.class);
Mockito.when(operations.submitHttpPostRequest(any(), anyString())).thenReturn("{\"response\":\"{\\\"run_id\\\":32423423}\\n\"}");
//System.out.println("==>"+operations.submitHttpPostRequest(null, ""));
...........
int runID = jobDelegate.executeJob(jobDetails);
System.out.println("Run ID here " + runID);
}
}
public class JobDelegate {
// This is an interface.. and the implementation is passed from spring-
context.xml
#Autowired
private JobManager jobImpl;
public int executeJob(JobDTO jobDto) {
............
return jobImpl.runBatchJob(jobDto);
}
}
public class DBJobManagerImpl implements JobManager{
#Autowired
private URIUtils uriUtils;
#Autowired
private HTTPOperations httpOperations;
#Override
public int runBatchJob(JobDTO jobDto) throws Exception {
UriComponentsBuilder uri = uriUtils.createURI(ConfigUtil.getUrI());
String response = httpOperations.submitHttpPostRequest(uri, runSubmitJson);
System.out.println("Response ==> " +response);
.................
}
}
I was able to resolve the issue using PowerMock.
Below the code
#RunWith(PowerMockRunner.class)
#ContextConfiguration(locations= "file:src/main/webapp/WEB-
INF/Enrichment_Context.xml")
#PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)
#PowerMockIgnore({ "javax.xml.*", "org.xml.*", "org.w3c.*",
"javax.management.*" })
#PrepareForTest({ HTTPOperations.class})
public class JobDelegateTest {
#Autowired
private JobDelegate jobSubmissionDelegate;
#Test
public void testExecuteJob() throws IOException {
PowerMockito.mockStatic(HTTPOperations.class);
PowerMockito.when(HTTPOperations.submitHttpPostRequest(Mockito.any(),
Mockito.anyString())).thenReturn("{\"response\":\"{\\\"run_id\\\":32423423}\\n\"}");
...................
int runID = jobSubmissionDelegate.executeJobSubmission(jobDetails);
}
}

JUNIT - Null pointer Exception while calling findAll in spring Data JPA

I am new to Junits and Mockito, I am writing a Unit test class to test my service class CourseService.java which is calling findAll() method of CourseRepository.class which implements CrudRepository<Topics,Long>
Service Class
#Service
public class CourseService {
#Autowired
CourseRepository courseRepository;
public void setCourseRepository(CourseRepository courseRepository) {
this.courseRepository = courseRepository;
}
public Boolean getAllTopics() {
ArrayList<Topics> topicList=(ArrayList<Topics>) courseRepository.findAll();
if(topicList.isEmpty())
{
return false;
}
return true;
}
}
Repository class
public interface CourseRepository extends CrudRepository<Topics,Long>{
}
Domain class
#Entity
#Table(name="Book")
public class Topics {
#Id
#Column(name="Topicid")
private long topicId;
#Column(name="Topictitle",nullable=false)
private String topicTitle;
#Column(name="Topicauthor",nullable=false)
private String topicAuthor;
public long getTopicId() {
return topicId;
}
public void setTopicId(long topicId) {
this.topicId = topicId;
}
public String getTopicTitle() {
return topicTitle;
}
public void setTopicTitle(String topicTitle) {
this.topicTitle = topicTitle;
}
public String getTopicAuthor() {
return topicAuthor;
}
public void setTopicAuthor(String topicAuthor) {
this.topicAuthor = topicAuthor;
}
public Topics(long topicId, String topicTitle, String topicAuthor) {
super();
this.topicId = topicId;
this.topicTitle = topicTitle;
this.topicAuthor = topicAuthor;
}
}
Following is the Junit class I have written but courseRepository is getting initialized to NULL and hence I am getting NullPointerException.
public class CourseServiceTest {
#Mock
private CourseRepository courseRepository;
#InjectMocks
private CourseService courseService;
Topics topics;
#Mock
private Iterable<Topics> topicsList;
#Before
public void setUp() {
MockitoAnnotations.initMocks(CourseServiceTest.class);
}
#Test
public void test_Get_Topic_Details() {
List<Topics> topics = new ArrayList<Topics>();
Mockito.when(courseRepository.findAll()).thenReturn(topics);
boolean result=courseService.getAllTopics();
assertTrue(result);
}
}
Change the setUp() method to:
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
Probably you are dealing with some problem on the framework to make the mocked class be injected by the framework.
I recommend to use Constructor Injection, so you don't need to rely on the reflection and #Inject/#Mock annotations to make this work:
#Service
public class CourseService {
private final CourseRepository courseRepository;
// #Autowired annotation is optional when using constructor injection
CourseService (CourseRepository courseRepository) {
this.courseRepository = courseRepository;
}
// .... code
}
The test:
#Test
public void test_Get_Topic_Details() {
List<Topics> topics = new ArrayList<Topics>();
Mockito.when(courseRepository.findAll()).thenReturn(topics);
CourseService courseService = new CourseService(courseRepository);
boolean result = courseService.getAllTopics();
assertTrue(result);
}

Resources