Hi I am new to groovy unit test using mockito.I am trying to figure how to write test case for daoImpl calss without really updating or inserting in database.
below is my code.
#Component
public class TransactionDAOImpl implements TransactionDAO {
#Autowired
StringUtilities stringUtilities;
#Autowired
private TransactionRepository transactionRespository;
#Override
#Transactional
public String create(List<DepositoryTransaction> depositoryTransaction) {
List<DepositoryTransaction> dep = transactionRespository.saveAll(depositoryTransaction);
LOGGER.debug("Recieved atm transaction : {} = {}", dep);
if (dep != null && !dep.isEmpty())
return stringUtilities.SUCCESS;
else
return stringUtilities.FAILURE;
}
}
#RunWith(MockitoJUnitRunner.class) // org.mockito.runners.MockitoJUnitRunner is deprecated so use org.mockito.junit.MockitoJUnitRunner instead
public class TransactionDAOImplTest{
#InjectMocks
private TransactionDAOImpl transactionDAOImpl;
#Mock
StringUtilities stringUtilities;
#Mock
private TransactionRepository transactionRespository;
List<DepositoryTransaction> depositoryTransaction=new ArrayList<>();
#Test
public void testCreateSaveAllNullReturn(){
when(transactionRespository.saveAll(depositoryTransaction)).thenReturn(null);
assertThat(transactionDAOImpl.create(depositoryTransaction)).isEqualTo(stringUtilities.SUCCESS); // i do not khnow if this is an enum ?
}
#Test
public void testCreateSaveAllEmptyReturn(){
when(transactionRespository.saveAll(depositoryTransaction)).thenReturn(new ArrayList<>());
assertThat(transactionDAOImpl.create(depositoryTransaction)).isEqualTo(stringUtilities.SUCCESS); // i do not khnow if this is an enum ?
}
#Test
public void testCreateSaveAllNotEmptyAndNotNullReturn(){
DepositoryTransaction obj=new DepositoryTransaction();
depositoryTransaction.add(obj);
when(transactionRespository.saveAll(depositoryTransaction)).thenReturn(depositoryTransaction);
assertThat(transactionDAOImpl.create(depositoryTransaction)).isEqualTo(stringUtilities.FAILURE); // i do not khnow if this is an enum ?
}
}
Related
Im trying to test a controller, Author Controller, which returns a view with a model. The problem is on the testInitUpdateAuthor() test where its not able to find the model or attribute name specifically. All other methods are fine with their model/attribute tests.
Any advice?
#Slf4j
#Controller
public class AuthorController {
private final AuthorService authorService;
private final String CREATEORUPDATEFORM = "author/createOrUpdateAuthor";
public AuthorController(AuthorService authorService) {
this.authorService = authorService;
}
#GetMapping("/author/{id}/update")
public String updateAuthor(#PathVariable("id") Long id, Model model) {
model.addAttribute("author", authorService.findById(id));
return CREATEORUPDATEFORM;
}
#ExtendWith(MockitoExtension.class)
#SpringBootTest
class AuthorControllerTest {
MockMvc mockMvc;
#Mock
AuthorService authorService;
#InjectMocks
AuthorController authorController;
#BeforeEach
void setUp() {
mockMvc = MockMvcBuilders.standaloneSetup(authorController).build();
}
#Test
void getIndex() throws Exception {
mockMvc.perform(get("/author/index"))
.andExpect(status().isOk())
.andExpect(view().name("author/index"))
.andExpect(model().attributeExists("authors"));
}
#Test
void testInitUpdateAuthor() throws Exception {
when(authorService.findById(anyLong())).thenReturn(Author.builder().id(1L).build());
mockMvc.perform(get("/author/1/update"))
.andExpect(status().isOk())
.andExpect(view().name("author/createOrUpdateAuthor"))
.andExpect(model().attributeExists("author"));
}
}
I am having dificulties with using MockMvc.
Here I have simple Service and controller classes:
Service:
#Slf4j
#Service
public class EmployeeService {
//...
public Employee GetSample() {
//...
//filling Employee Entities
return new Employee(
"Harriet"
, "random"
, 25);
}
}
controller:
#RestController
#RequestMapping(value = "/info")
#RequiredArgsConstructor(onConstructor = #__(#Autowired))
#Validated
public class EmployeeController {
private final EmployeeService employeeService;
#PostMapping("/GetEmployee")
public ResponseEntity<Employee> GetEmployee() {
Employee employee = employeeService.GetSample();
return new ResponseEntity<>(employee, HttpStatus.OK);
}
}
Test:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest
public class EmployeeTestCase {
private MockMvc mockMvc;
#InjectMocks
private EmployeeController EmployeeController;
#Mock
private EmployeeService employeeService;
#Before
public void setUp() {
this.mockMvc = MockMvcBuilders.standaloneSetup(employeeController).build();
}
#Test
public void getEmployee() throws Exception {
this.mockMvc.perform(MockMvcRequestBuilders.post("/info/GetEmployee")).andDo(print());
}
}
when I try to use MockMvc I get null body. It seems employee is null. But I didn't understand why.
I thought that when test uses perform, it should initialise employee and later on it should't be null.
I tried to cut the code as much as possible. I hope it is not long.
Note : also tried to use Mockito.when(employeeController.GetEmployee()).thenCallRealMethod();
The #SpringBootTest annotation loads the complete Spring application
context. That means you do not mock your layers
(Services/Controllers).
If you wanted to test specific layers of your application, you could look into test slice annotations offered by Springboot: https://docs.spring.io/spring-boot/docs/current/reference/html/test-auto-configuration.html
In contrast, a test slice annotation only loads beans required to test a particular layer. And because of this, we can avoid unnecessary mocking and side effects.
An example of a Test Slice is #WebMvcTest
#ExtendWith(SpringExtension.class)
#WebMvcTest(controllers = HelloController.class,
excludeFilters = {
#ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = SecurityConfig.class)
}
)
public class HelloControllerTest {
#Autowired
private MockMvc mvc;
#Test
public void hello() throws Exception {
String hello = "hello";
mvc.perform(get("/hello"))
.andExpect(status().isOk())
.andExpect(content().string(hello));
}
#Test
public void helloDto() throws Exception {
String name = "hello";
int amount = 1000;
mvc.perform(
get("/hello/dto")
.param("name", name)
.param("amount", String.valueOf(amount)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.name", is(name)))
.andExpect(jsonPath("$.amount", is(amount)));
}
}
However if you really wanted to load up the SpringBoot Application context, say for an Integration Test, then you have a few options:
#SpringBootTest
#AutoConfigureMockMvc
public class TestingWebApplicationTest {
#Autowired
private MockMvc mockMvc;
#Test
public void shouldReturnDefaultMessage() throws Exception {
this.mockMvc.perform(get("/")).andDo(print()).andExpect(status().isOk())
.andExpect(content().string(containsString("Hello, World")));
}
}
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest
public class AuctionControllerIntTest {
#Autowired
AuctionController controller;
#Autowired
ObjectMapper mapper;
MockMvc mockMvc;
#Before
public void setUp() throws Exception {
System.out.println("setup()...");
mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
}
#Test
public void create_ValidAuction_ShouldAddNewAuction() throws Exception {
final Auction auction = new Auction(
"Standing Desk",
"Stand up desk to help you stretch your legs during the day.",
"Johnnie34",
350.00);
mockMvc.perform(post("/auctions")
.contentType(MediaType.APPLICATION_JSON)
.content(toJson(auction)))
.andExpect(status().isCreated());
}
}
Lets say you don't want to load up any layers at all, and you want to mock everything, such as for example a Unit Test:
#RunWith(MockitoJUnitRunner.class)
class DemoApplicationTest {
#Mock
private UserRepository userRepository;
private Demo noneAutoWiredDemoInstance;
#Test
public void testConstructorCreation() {
MockitoAnnotations.initMocks(this);
Mockito.when(userRepository.count()).thenReturn(0L);
noneAutoWiredDemoInstance = new Demo(userRepository);
Assertions.assertEquals("Count: 0", noneAutoWiredDemoInstance.toString());
}
}
Here is the code I am using.
The test class:
#ExtendWith(MockitoExtension.class)
#SpringBootTest
public class XTest{
#Mock
XRepository xRepository ;
#Mock
XServiceImpl xServiceImpl ;
X x = new X();
XC xC= new XC();
List<X> lX= new ArrayList<X>();
#BeforeEach
void createProcedure(){
x.setId((long)1);
x.setDescription("First one");
x.setValue("10");
xC.setCode("X");
x.setCategory(xC);
lX.add(x);
}
#Test
void testGetXByCode() {
Mockito.when(xRepository.findByCode(Mockito.anyString())).thenReturn(lX);
List<X> xL= xServiceImpl.getProcedureByCode("X");
System.out.println(lX.size());
assertEquals(1,xL.size());
assertNotEquals("Y", xL.get(0).getCategory().getCode() );
}
}
My service implementation class:
#Service
public class XServiceImpl implements XService {
private final XRepository xRepository;
#Autowired
public XServiceImpl(XRepository xRepository) {
this.xRepository = xRepository;
}
#Transactional
public List<X> getXByCode(String code) {
List<X> x= new ArrayList<>();
try {
x= xRepository.findByCode(code);
if (!x.isEmpty()) {
return x;
}
} catch (Exception ex) {
}
return null;
}
}
And my repository code is as follows:
#Repository
public interface XRepository extends JpaRepository<X, Long>{
public Optional<X> findById(Long id);
}
Both the test cases seem to be failing. Can anyone help me out with this?
The actual size of the list is 1 which is being printed. But when then return doesn't seem to be returning the same one.
#Mock creates mock. You should annotate XServiceImpl with #InjectMocks so that creates an instance of the class and injects the mocks that are created with the #Mock annotations (such as XRepository).
#InjectMocks
XServiceImpl xServiceImpl;
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.
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);
}