In a class under test, if its constructor takes in an abstract class parameter can we mock it using mockito?
Ex
public abstract AbstractClass{
}
//Class under test
public class SourceClass{
SourceClass(AbstractClass abstractClass){}
}
#RunWith(MockitoJUnitRunner.class
public SourceClassTest{
#Mock
AbstractClass abstractClass;
}
whenever I do this i get this error
java.lang.ExceptionInInitializerError
Ther version of mockito I am using i 1.8.5
Well, this code below works fine, just tell me if I need to add some comments to explain what I wrote, ok? (hey, I am using Mockito 1.10.8):
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
abstract class AbstractClassToTest {
public abstract String doSomething();
}
class ConcreteClass {
private String something;
public ConcreteClass(AbstractClassToTest aClass){
this.something = aClass.doSomething();
}
public String getSomething(){
return this.something;
}
}
#RunWith(MockitoJUnitRunner.class)
public class TempTest {
#Mock
private AbstractClassToTest myClass;
#Test
public void canAbstractClassToTestBeMocked() {
String expectedResult = "hello world!";
Mockito
.when(myClass.doSomething())
.thenReturn(expectedResult);
String actualResult = myClass.doSomething();
Assert.assertEquals(expectedResult, actualResult);
}
#Test
public void canConcreteClassBeInstantiatedWithMock() {
String expectedResult = "hello world!";
Mockito
.when(myClass.doSomething())
.thenReturn(expectedResult);
ConcreteClass concrete = new ConcreteClass(myClass);
String actualResult = concrete.getSomething();
Assert.assertEquals(expectedResult, actualResult);
}
}
You cannot mock abstract classes, you have to mock a concrete one and pass that along. Just as regular code can't instantiate abstract classes.
Related
I have a class Room, where I inject Optional Person object, this is coming null while running testSuccess. My understanding is it should come non null, since I am setting this to new Person() at the start of the test. Why is it coming null?
public class Room{
#Inject
private Optional<Person> person1
//this is coming null when running test
}
My unit test
public class RoomTest {
#Inject Mocks
private Room testRoom
.....
//Other mocks
private Optional<Person> testPerson
//Not able to mock this since its optional, hence directly setting value in unit test.
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
#Test
public void testSuccess() {
testPerson = Optional.of(new Person());
....
}
}
As the name implies, #InjectMocks only injects #Mocks. The testPerson is not a mock. Why not just add an #Inject-ing constructor to the Room class that would accept a person? This way you could just instantiate a testRoom in your test method and your dependency injection will still work.
public class Room{
private Optional<Person> person;
#Inject
public Room(Optional<Person> person) {
this.person = person;
}
}
public class RoomTest {
#Test
public void testSuccess() {
Optional<Person> testPerson = Optional.of(new Person());
Room room = new Room(testPerson);
...
}
}
That said, if you absolutely want to use the annotations and adding the constructor is not an option for you then you can use PowerMock runner to mock the Optional. Conceptually, it can look like the code below. But usually, if you have to use PowerMock there might be something wrong with the code :)
public class Room{
#Inject
private Optional<Person> person;
}
// This is for JUnit4. Using Powermock with JUnit5 will be more involved
#RunWith(PowerMockitoRunner.class)
#PrepareForTest(Optional.class) // to mock the final class
public class RoomTest {
#InjectMocks
private Room testRoom;
#Mock
private Optional<Person> testPerson;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
#Test
public void testSuccess() {
...
}
}
I am writing JUnit Test case with Mockito for a class which has two methods methodA,methodB. I would like to mock the call to the methodA from methodB in my test case.Some one help me.pls
Here is the class:
public Class Test{
public static List<Object> methodA() {
...
return list;
}
public static List<Object> methodB() {
...
list = methodA();
return list;
}
}
You will need to use PowerMockito to mock the static method.
Example:
package unitest;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest(unitest.Test.class)
public class TestTest {
#Test
public void testMethodB() {
PowerMockito.mockStatic(unitest.Test.class);
PowerMockito.when(unitest.Test.methodA()).thenReturn(new ArrayList());
List b = unitest.Test.methodB();
org.junit.Assert.assertNotNull(b);
}
}
I am trying to create a mock data for Dao class. Test case is running successfully but it is returning null data. I searched and implemented #Mock, #InjectMocks, Inititated MockitoAnnotation but still it is not working. The project is in spring. Context path is also correct. I have not used any other methods. First for running I am trying to just call a method and print. Please help me to solve this error.
RegionManager Class:
#Service("regionManager")
public class RegionManager implements RegionManagerIntf {
#Autowired
RegionDaoIntf regionInquiry;
private RegionDao regionDao;
#Override
public ListPojo retrieveData(String Id, String details, String code) {
return regionInquiry.retrievePData(Id, details, code);
}
public RegionDao getRegionDao() {
return regionDao;
}
public void setRegionDao(RegionDao regionDao) {
this.regionDao = regionDao;
}
}
Dao Class:
#Component
public class RegionProcessorFactory implements RegionProcessorIntf {
private static final Logger logger = Logger
.getLogger(RegionProcessorFactory.class);
#Override
public ListPojo retrieveData(String Id,
String details, String code) {
ListPojo listPojo = new ListPojo();
//Do some action
return listPojo;
}
}
ListPojo:
It contains getter setters.
Test Class:
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.test.context.ContextConfiguration;
import com.fasterxml.jackson.databind.ObjectMapper;
#RunWith(MockitoJUnitRunner.class)
#ContextConfiguration({"classpath*:spring/beanRefContext.xml"})
public class RegionManagerTest
{
private String Id = "12345";
private String Code = "123";
private String details = "12";
ObjectMapper mapper;
#Mock
private RegionProcessorFactory dao;
#Mock
private ListPojo listPojo;
#InjectMocks
private RegionManager service;
/**
* Before method will be called before executing every test case
*/
#Before
public void initialize() {
System.out.println("In initialize");
MockitoAnnotations.initMocks(this);
dao = mock(RegionProcessorFactory.class);
listPojo = mock(ListPojo.class);
service = new RegionManager();
service.setRegionDao(dao);
}
#Test
public void CreateDatabaseMock() throws Exception
{
System.out.println("dao result :: "+dao.retrieveData(Id, "", ""));
when(dao.retrieveData(Id, "", "")).thenReturn(listPojo);
verify(dao).retrieveData(Id, "", "");
}
/**
* After method will be called after executing every test case
*/
#After
public void TearDownClass() {
}
}
First: If you are using #RunWith(MockitoJUnitRunner.class) there is no need for MockitoAnnotations.initMocks(this); more on that here
Second: Everything with #Mock will be mocked and mockito will try to inject it into object annotated with #InjectMocks which mockito will instantiate(in old mockito versions you had to create the object yourself) so following lines are not needed:
dao = mock(RegionProcessorFactory.class);
listPojo = mock(ListPojo.class);
service = new RegionManager();
service.setRegionDao(dao);
Third: The actual execution should come after stubbing
#Test
public void CreateDatabaseMock() throws Exception{
when(dao.retrieveData(Id, "", "")).thenReturn(listPojo);
System.out.println("dao result :: "+dao.retrieveData(Id, "", ""));
verify(dao).retrieveData(Id, "", "");
}
I would like to test the behaviour configured by my Katharsis ResourceRepository (katharsis-spring 2.1.7):
import io.katharsis.queryParams.QueryParams;
import io.katharsis.repository.ResourceRepository;
import org.springframework.stereotype.Component;
#Component
public class UserResourceRepository implements ResourceRepository<UserDTO, String> {
#Autowired
private UserRepository databaseRepository;
#Override
public UserDTO findOne(String email, QueryParams queryParams) {
return null;
}
#Override
public Iterable<UserDTO> findAll(QueryParams queryParams) {
return null;
}
#Override
public Iterable<UserDTO> findAll(Iterable<String> iterable, QueryParams queryParams) {
return null;
}
#Override
public void delete(String email) {
}
#Override
public UserDTO save(UserDTO s) {
return null;
}
}
I would like to test it in a similar way as I do it with normal, Spring Controllers, using Mockito to mock database repository and using MockMvc:
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;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import java.util.Optional;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
#RunWith(MockitoJUnitRunner.class)
public class UserJsonApiTest {
#InjectMocks
private UserResourceRepository resourceRepository;
#Mock
private UserRepository databaseRepository;
private MockMvc mockMvc;
#Before
public void setup() {
mockMvc = MockMvcBuilders.standaloneSetup(resourceRepository).build();
}
#Test
public void first() throws Exception {
Optional<UserEntity> user = Optional.of(new UserEntity().
id(1).
email("test#test").
firstName("test first name").
lastName("test last name").
pass("test pass"));
when(
databaseRepository.
findOneByEmail(user.get().getEmail())).
thenReturn(user);
mockMvc.perform(
get("/users/" + user.get().email())).
andExpect(status().isOk())
;
}
}
Obviously, this code doesn't work because my Katharsis UserResourceRepository is not really a Controller. So far I have learned (from logs) that it is actually using some filters mappings and class named io.katharsis.spring.KatharsisFilterV2.
Is there any way to use MockMvc for such test? If not - is there any other way I could test it without starting the whole server (with mocking)?
You could use an embedded Server - like UndertowJaxrsServer - and inject the KatharsisFeature:
Create a class (MyApp) which extends Application public static class MyApp extends Application { and deploy it to the embedded server server.deploy(MyApp.class);
in this Class, overwrite getClasses and add a second class (KatharsisFeatureTest) which implements Feature KatharsisFeatureTest implements Feature
in KatharsisFeatureTest you can then register a KatharsisFeature and there you can overwrite JsonServiceLocator and inject the mock.
Sound a little bit complicated, but works like charm :)
Have a look at my implementation.
.
#RunWith(MockitoJUnitRunner.class)
public class EndpointResourceTest {
#Mock
private EndpointService endpointService;
#InjectMocks
private final static EndpointResourceV1 endpointRessource = new EndpointResourceV1();
private static UndertowJaxrsServer server;
#BeforeClass
public static void beforeClass() throws Exception {
server = new UndertowJaxrsServer();
server.deploy(MyApp.class);
server.start();
}
#Test
public void testGetEndpoint() throws URISyntaxException {
Mockito.when(endpointService.getEndpoint("SUBMIT")).thenReturn(new EndpointDTO("SUBMIT", "a", "b"));
Client client = ClientBuilder.newClient();
Response response = client.target(TestPortProvider.generateURL("/api/endpoints/SUBMIT"))
.request(JsonApiMediaType.APPLICATION_JSON_API)
.get();
Assert.assertEquals(200, response.getStatus());
String json = response.readEntity(String.class);
Assert.assertTrue(json.contains("SUBMIT"));
Assert.assertTrue(json.contains("a"));
Assert.assertTrue(json.contains("b"));
Mockito.verify(endpointService, Mockito.times(1)).getEndpoint("SUBMIT");
}
#AfterClass
public static void afterClass() throws Exception {
server.stop();
}
#ApplicationPath("/api")
public static class MyApp extends Application {
#Override
public Set<Class<?>> getClasses() {
HashSet<Class<?>> classes = new HashSet<Class<?>>();
classes.add(KatharsisFeatureTest.class);
return classes;
}
}
public static class KatharsisFeatureTest implements Feature {
#Override
public boolean configure(FeatureContext featureContext) {
featureContext
.property(KatharsisProperties.RESOURCE_SEARCH_PACKAGE, "...")
.register(new io.katharsis.rs.KatharsisFeature(
new ObjectMapper(), new QueryParamsBuilder(new DefaultQueryParamsParser()), new SampleJsonServiceLocator() {
#Override
public <T> T getInstance(Class<T> clazz) {
try {
if (clazz.equals(EndpointResourceV1.class)) {
return (T) endpointRessource;
}
return clazz.newInstance();
}
catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}));
return true;
}
}
}
So i have a class that needs to be tested. Lets call it ClassToTest. It has a couple of Dao objects as fields.
Public class ClassToTest {
#Autowired
MyDao dao;
void methodToTest() {
dao.save(something);
}
}
As you can see ClassToTest does not contain any constructor or setter and I am using spring to autowire the fields.
Now, I have a base test class with all the dependencies that classToTest requires:
public abstract BaseTest {
#Mock
MyDao dao;
}
And the testClass extends this BaseTest class :
public class TestClass extends BaseTest {
#InjectMocks
ClassToTest classToTest = new ClassToTest();
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
#Test
public void test() {
classToTest.methodToTest();
}
}
This results in a null pointer exception when the save happens. However, if i change setup method to this :
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
classToTest.dao = dao;
}
the test passes.
My understanding was that when a class does not have a constructor or a setter, InjectMocks would inject the mocks by using field injection. Why is that not happening here?
Figured out that this is a bug in the 1.8.5 version that i was using : https://code.google.com/p/mockito/issues/detail?id=229.
Upgrading 1.10 fixed the issue.