I am new to Mockito framework , I have a rest APi that connects my application to jasper server and do report related operations.I want to write junit test cases for rest API using mockito framework.
here i have class called Repositoryclient , Its constructor have instance of JasperServerInfo DAO class.
public class RepositoryClient {
public RepositoryClient(ServerInfo serverInfo) {
this.info = serverInfo;
try {
Session = Client.authenticate(info.username.trim(), info.password.trim());
}
catch (Exception e) {
}
}
public void Templates() { //this method brings list of present report in jasper server repository
try {
OperationResult<...> result = ....;
} catch (Exception e) {
INodeProcessor.logger.warn(e.toString());
throw Error.REPORT_TEMPLATE_LIST_ERROR.with();
}
}
So how to write JUnit test cases using mockito for this class please guide me through. Thank you in advance.
Well, the code could be improved to make it actually testable...
At the moment, there is no really good way to write unit tests for your code, since the constructor creates a JasperserverRestClient without any chance to change it. The least you can do is add another constructor (may be package access) to allow another JasperserverRestClient to be used. (Alternatively you could think about using a Factory pattern. but this might be to complicated.)
Then you could mock that...
JasperserverRestClient jasperServerClient = Mockito.mock( JasperserverRestClient.class );
RestClientSession session = Mockito.mock( RestClientSession.class );
Mockito.when( jasperServerClient.authenticate( "x", "y")).thenReturn( session );
RepositoryClient repositoryClient = new RepositoryClient(jasperServerClient);
This would at least allow you to test, that authenticate is called with the correct parameters via Mockito.verify.
Also it would allow you to test that the listTemplates method calls the session with the correct parameters (of course you'll need to so some more mocking there).
An additional constructor, assuming your tests are in the same package, would look like this:
RepositoryClient(JasperserverRestClient httpRestClient, JasperServerInfo serverInfo) {
this.info = serverInfo;
this.httpRestClient = httpRestClient;
try {
restClientSession = httpRestClient.authenticate(info.username.trim(), info.password.trim());
}
catch (Exception e) {
INodeProcessor.logger.warn(e.toString());
throw Error.REPOSITORY_CLIENT_ERROR.with();
}
}
This way you can inject a mocked instance of your JasperserverRestClient into your object.
A test of your listTemplates method would (addtionally) look like this...
X resourcesService = Mockito.mock( X.class ); // No clue what the resourcesService() method is supposed to return, fill that in here
Mockito.when ( restClientSession.resourcesService() ).thenReturn ( resourcesService );
...This will allow the part restClientSession.resourcesService() to work. Next...
Y resources = Mockito.mock( Y.class ); // Same thing here, don't know what resources() should return, insert that class here
Mockito.when( resourcesService.resources()).thenReturn ( resources );
This will allow the resources() call to work.
Next we do some trickery:
Mockito.when( resources.parameter( Mockito.anyString(), Mockito.anyString()).thenReturn(resources); // assuming that ResourceSearchParameter constant is a String
This will allow the parameter() calls to work by returning the same resources() object.
And so on... You will need to when(...).thenReturn(...) the search method to return a OperationResult<ClientResourceListWrapper>, etc. but that's the same stuff as above.
And in the end, we could verify that the methods were called with the right parameters...
Mockito.verify( resources, Mockito.times(1)).parameter(ResourceSearchParameter.FOLDER_URI, info.reportDirectory);
Mockito.verify( resources, Mockito.times(1)).parameter(ResourceSearchParameter.RECURSIVE, "false"
Mockito.verify( resources, Mockito.times(1)).search();
getting started example that i have :
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
#Test(priority = 31, groups = "success")
public void mockExample() {
Category category1 = mock(Category.class);
when(category1.getName()).thenReturn("Yess!!!");
System.out.println(category1.getName());
}
will print:"Yess!!!"
you can read from here :
http://examples.javacodegeeks.com/core-java/mockito/mockito-hello-world-example/
#RunWith(SpringJUnit4ClassRunner.class)
public class UserControllerTest {
#InjectMocks
private UserController userController;
#Mock
private RequestAttributes attrubutes;
#Mock
private UserService userService;
private MockMvc mockMvc;
#Before
public void setup() {
RequestContextHolder.setRequestAttributes(attrubutes);
this.mockMvc = MockMvcBuilders.standaloneSetup(userController).build();
}
#Test
public void getUserinfoDetails() {
String userId = "123";
String userName = "Test145";
List<UserDto> userDtoList = new ArrayList<>();
Mockito.when(userService.getAllUserInfo()).thenReturn(userDtoList);
Assert.assertNotNull(userController.getUserinfo());
Assert.assertNotNull(userDtoList);
Assert.assertNotNull(userId);
Assert.assertNotNull(userName);
}
#Test
public void getUserByIdDetails() {
String userId = "123";
UserDto userDto = new UserDto();
Mockito.when(userService.getUserByUserId(userId)).thenReturn(userDto);
Assert.assertNotNull(userController.getUserById(userId));
Assert.assertNotNull(userDto);
Assert.assertNotNull(userId);
}
}
===========================================================================
for reference use below link:(step by step explanation)
https://www.youtube.com/watch?v=yGLOexeJfKA&t=17s
Related
I am using Spring framework 2.4.4 and Intellij Ultimate 2020
I would like to test this method tryGetUser on which I am passing HttpSession, but I can't resolve the problem, because when I am mocking it and setAttribute(); at the //Arrange part of the method it always ends with currentUserUsername to be null.
public User tryGetUser(HttpSession session) {
String currentUserUsername = (String) session.getAttribute("currentUserUsername");
***// Here this local variable currentUsername is always null;***
if (currentUserUsername == null) {
throw new AuthorizationException("No logged in user.");
}
try {
return userService.getByUsername(currentUserUsername);
} catch (EntityNotFoundException e) {
throw new AuthorizationException("No logged in user.");
}
}
Here you can see how I am trying to Mock it, but actually, the session is remaining empty or I don't know, but when the service method starts to execute the attribute is not there.
#ExtendWith(MockitoExtension.class)
public class LoginServiceMvcTests {
#Mock
UserRepository mockUserRepository;
#Mock
UserService mockUserService;
#InjectMocks
MockHttpSession mockHttpSession;
#InjectMocks
LoginServiceMvc userService;
private User junkie;
private User organizer;
#BeforeEach
public void setup() {
junkie = Helpers.createJunkie();
organizer = Helpers.createOrganizer();
}
#Test
public void tryGetUser_Should_GetUserFromSession_When_UserIsLogged() {
// Arrange
mockHttpSession.setAttribute("luboslav", junkie);
Mockito.when(mockUserService.getByUsername("luboslav"))
.thenReturn(junkie);
// Act
userService.tryGetUser(mockHttpSession);
// Assert
Mockito.verify(mockUserService, Mockito.times(1))
.getByUsername("luboslav");
}
}
From Jon skeet answer Mockito doesn't work that way, so you need to actually mock the call instead of setting attribute
Mockito.when(mockHttpSession. getAttribute("currentUserUsername"))
.thenReturn("name");
And also HttpSession should be annotated with #Mock not #InjectMocks
#Mock
HttpSession httpSession;
Use MockHttpSession, which is an actual real object (not just a Mockito interface mock) that is intended for exactly this type of testing. It's basically an empty/blank container, so you don't have to mock out all the standard behavior, just fill it with whatever attributes you want.
At first I want to sorry for my english.
I started to make some unit tests (i've never done this before, i'm a new guy in programming).
I have to test simple adding product to database (DynamoDB) method using mockito.verify but I have
"Wanted but not invoked. Actually, there were zero interactions with this mock."
Error and I don't know what to do.
This is my method code (in KitchenService class):
public Product addProduct(Product content) {
ObjectMapper objectMapper = new ObjectMapper();
String mediaJSON = null;
String authorJSON = null;
String productKindsJSON = null;
try {
mediaJSON = objectMapper.writeValueAsString(content.getMedia());
authorJSON = objectMapper.writeValueAsString(content.getAuthor());
productKindsJSON = objectMapper.writeValueAsString(content.getProductKinds());
} catch (JsonProcessingException e) {
logger.log(e.getMessage());
}
Item item = new Item()
.withPrimaryKey("id", UUID.randomUUID().toString())
.with("name", content.getName())
.with("calories", content.getCalories())
.with("fat", content.getFat())
.with("carbo", content.getCarbo())
.with("protein", content.getProtein())
.with("productKinds", productKindsJSON)
.with("author", authorJSON)
.with("media", mediaJSON)
.with("approved", content.getApproved());
Item save = databaseController.saveProduct(PRODUCT_TABLE, item);
logger.log(save + " created");
return content;
}
And this is test code:
#Test
public void addProduct() throws Exception {
KitchenService instance = mock(KitchenService.class);
Product expectedProduct = new Product();
expectedProduct.setName("kaszanka");
expectedProduct.setCalories(1000);
expectedProduct.setFat(40.00);
expectedProduct.setCarbo(20.00);
expectedProduct.setProtein(40.00);
expectedProduct.setProductKinds(Collections.singletonList(ProductKind.MEAT));
expectedProduct.setApproved(false);
Author expectedAuthor = new Author();
expectedAuthor.setId("testID");
expectedAuthor.setName("Endrju Golota");
expectedProduct.setAuthor(expectedAuthor);
Media expectedMedia = new Media();
expectedMedia.setMediaType(MediaType.IMAGE);
expectedMedia.setName("dupajasia");
expectedMedia.setUrl("http://blabla.pl");
expectedProduct.setMedia(expectedMedia);
verify(instance, times(1)).addProduct(expectedProduct);
}
This is what I got after test:
Wanted but not invoked:
kitchenService.addProduct(
model.kitchen.Product#a0136253
);
-> at service.kitchen.KitchenServiceTest.addProduct(KitchenServiceTest.java:80)
Actually, there were zero interactions with this mock.
Can someone tell me what im doing wrong?
What you should mock and verify is the databaseController dependency:
#Test
public void addProduct() throws Exception {
KitchenService instance = new KitchenService(); // you should create the class under test
DatabaseController controllerMock = mock(DatabaseController.class); // mock the controller
instance.setController(controller); // inject the mock
...
// Act
instance.addProduct(expectedProduct);
// Assert
verify(controller).saveProduct(Mockito.eq(PRODUCT_TABLE), Mockito.any(Item.class));
}
You should verify that the database is called within the service.. checking that it was invoked with any Item object should be enough.
Mocking is a tool that you only use for dependencies of the class that is being tested.
It appears that your test does not care about the Author, Media, and Product objects,
these are just dependencies of the method you want to test;
mock them.
Organization will greatly help your test;
do something like this:
public class TestKitchenService
{
private static String VALUE_PRODUCT_NAME = "VALUE_PRODUCT_NAME";
... use constants for other values as well. The value of the constant does not matter.
#InjectMocks
private KitchenService classToTest;
private InOrder inOrder;
#Mock
private Author mockAuthor;
#Mock
private DatabaseController mockDatabaseController;
#Mock
private Logger mockLogger;
#Mock
private Media mockMedia;
#Mock
private Product mockProduct;
#After
public void afterTest()
{
inOrder.verifyNoMoreInteractions();
verifyNoMoreInteractions(mockAuthor);
verifyNoMoreInteractions(mockDatabaseController);
verifyNoMoreInteractions(mockLogger);
verifyNoMoreInteractions(mockMedia);
verifyNoMoreInteractions(mockProduct);
}
#Before
public void beforeTest()
{
MockitoAnnotations.initMocks(this);
doReturn(mockAuthor).when(mockProduct).getAuthor();
doReturn(mockMedia).when(mockProduct).getMedia();
doReturn(VALUE_PRODUCT_NAME).when(mockProduct).getName();
doReturn(Collections.singletonList(ProductKind.MEAT)).when(mockProduct).getProductKinds();
... doReturns for the other product values.
inOrder = inOrder(
mockAuthor,
mockDatabaseController,
mockLogger,
mockMedia,
mockProduct);
ReflectionTestUtils.setField(
classToTest,
"databaseController",
mockDatabaseController);
ReflectionTestUtils.setField(
classToTest,
"logger",
mockLogger);
}
#Test
public void addProduct_success()
{
final Product actualResult;
actualResult = classToTest.addProduct(mockProduct);
assertEquals(
mockProduct,
actualResult);
inOrder.verify(mockProduct).getMedia();
inOrder.verify(mockProduct).getAuthor();
inOrder.verify(mockProduct).getProductKinds();
inOrder.verify(mockProduct).getName();
... inOrder.verify for the other product values.
inOrder.verify(mockDatabaseController).saveProduct(
eq(PRODUCT_TABLE),
any(Item.class));
}
}
The only things that should be mocked -- if anything -- are the ObjectMapper and databaseController. One only mocks collaborator objects, and almost never the system/class under test (very rare cases exist for "spying" on the SUT). And depending on what the ObjectMapper is and how transparent it's operation is, you may not really want to even mock that. Furthermore, as your implementation code is written instantiating the ObjectMapper by directly calling a constructor, you can't even mock it.
While I love the use of Mockito and mock objects, sometimes it is worthwhile to simply test with as many real objects as possible. This is especially true when your collaborators are simple, straightforward, have no side effects, and don't require complex initialization or setup. Only use mocks when it simplifies the test setup or verification.
I have foolowing class which I would like to mock:
BusineesLayer:
/**
* Created by Alexandr on 14.05.2016.
*/
public class BusineesLayer {
public OrderModel orderModel;
public DbService dbService;
...
public BusineesLayer(OrderModel orderModel,DbService dbService) {
this.orderModel = orderModel;
dbService = dbService;
}
public BusineesLayer() {
}
public boolean checkItemsInDb(List<Items> items) throws HandleOrderExeption {
...
return result
}
public boolean handleOrder() throws HandleOrderExeption {
checkItemsInDb(orderModel.getItemsList());
boolean res =dbService.addOrder(orderModel.getItemsList(),
orderModel.getCustumerName(),
countTotalSum(orderModel.getItemsList())
);
return res;
}
}
I would like to test hanldeOrder() method and in order to make it less excess insted of checkItemsinDb() inside invoke "true";
So, my test looks like this:
#Test
public void handleorderTest() {
...
BusineesLayer layer = Mockito.mock(BusineesLayer.class);
layer.dbService = busineesLayer.dbService;
layer.orderModel = busineesLayer.orderModel;
Mockito.when(layer.checkItemsInDb()).thenReturn(true);
boolean res = layer.handleOrder();
assertThat(res, equalTo(true));
}
but it always return false and doesn't go through handlOrder() at all
Is any ways to solve it? Or how can I refactor my code to test it?
You do not test mocks, you use mocks to help you test.
I think you've just become confused at how you are using mocks. Mocks allow us to simulate and can responses to objects we are testing. If you're testing the handleOrder method, then you should mock anything that interacts with that method, in this case DbService and OrderModel.
#Test
public void handleorderTest() {
BusineesLayer layer = new BusineesLayer(); //we are testing this!
DbService dbService = Mockito.mock(DbService.class);
OrderModel orderModel = Mockito.mock(OrderModel.class);
layer.dbService = dbService;
layer.orderModel = orderModel;
Mockito.when(orderModel.getItemsList()).thenReturn(new ArrayList<Items>());
Mockito.when(dbService.foo()).thenReturn(true);
//mock up multiple calls so your service will provide true
boolean res = layer.handleOrder();
assertThat(res, equalTo(true));
//repeat for false, and so on
}
If, however, you are trying to test the dbService call, then you should create a test for it without the business layer at all. The business layer doesn't depend on anything except calls to other methods, so whether you use those real objects or mocked versions of those objects, the functionality should be the same. The business logic only appears to fail if DBService or OrderModel break, so you would test service and model separately (without involving the business layer) to test those.
User getUser(int id) {
User user = service.get( id );
if( user != null ) {
user.Stuff = getUserStuff( id );
return User;
}
throw new NotFoundException();
}
Stuff getUserStuff( int id ) {
stuffGetter.getStuff( id ); // stuff getter makes a rest call
return Stuff;
}
Using EasyMock, how would i test the getUser(id) method. The confusing part for me is that getUserStuff(id) makes an external call which I dont want to make when testing getUser.
As mentioned by other users in the comments, you need to provide mock instances of the objects that are making the calls that you wish to mock out.
So within getUser(id) I can see a call to an object called service which should be mocked out. So use a mock instance of the service class and then the call to get(id) can be mocked out.
Then within the getUserstuff(id) method, it uses a stuffGetter object which could be mocked out again. Then the method being called could have expectations set up for it.
(An alternative to this could also be to set up a partial mock and mock the getUSerstuff(id) method all together, but this is a bit beyond what you're looking to do I think)
With those things in mind, I created the following class to test your described use case:
public class ClassToTest {
private final Service service;
private final StuffGetter stuffGetter;
public ClassToTest() {
this( new Service(), new StuffGetter() );
}
public ClassToTest(final Service service, final StuffGetter stuffGetter) {
this.service = service;
this.stuffGetter = stuffGetter;
}
public User getUser(final int id) {
final User user = this.service.get( id );
if( user != null ) {
user.stuff = getUserStuff( id );
return user;
}
throw new NotFoundException();
}
public Stuff getUserStuff( final int id ) {
return this.stuffGetter.getStuff( id );
}
}
Having the constructors set up like this gives me the ability to set up mock instances of the dependencies within the tests. So what follows is a test for the getUser(id) method that uses mocks for the two objects. It uses the basic EasyMock concepts of expect, replay and verify.
Create mock instances for the objects you need to mock the method calls on, in this case the service and the stuffGetter.
Write expectations for the method calls using the expect method. This is where you specify what will be returned if the method you are mocking is not a void method.
Replay the mock objects, in this case replay both of them. This means you can no longer add any expectations because the mocks are no longer in record mode for recording expectations.
Execute your tests.
Verify that the expected method calls on your mocks were executed as desired.
The tests looks like this:
import static org.junit.Assert.assertEquals;
import org.easymock.EasyMock;
import org.junit.Test;
public class ClassToTestTest {
#Test
public void thatGetIdCallsExpectedMockMethods() {
final User user = new User();
final Stuff userStuff = new Stuff();
final Service mockService = EasyMock.createMock(Service.class);
final StuffGetter mockStuffGetter = EasyMock.createMock(StuffGetter.class);
EasyMock.expect( mockService.get(15) ).andReturn( user );
EasyMock.expect( mockStuffGetter.getStuff(15) ).andReturn( userStuff );
EasyMock.replay( mockService, mockStuffGetter );
final ClassToTest classToTest = new ClassToTest( mockService, mockStuffGetter );
final User returnedUser = classToTest.getUser(15);
assertEquals(returnedUser, user);
assertEquals(returnedUser.stuff, userStuff);
EasyMock.verify( mockService, mockStuffGetter );
}
}
How do i mock the variables instantiated at class level..I want to mock GenUser,UserData. how do i do it...
I have following class
public class Source {
private GenUser v1 = new GenUser();
private UserData v2 = new UserData();
private DataAccess v3 = new DataAccess();
public String createUser(User u) {
return v1.persistUser(u).toString();
}
}
how do i mocked my v1 is like this
GenUser gu=Mockito.mock(GenUser.class);
PowerMockito.whenNew(GenUser.class).withNoArguments().thenReturn(gu);
what i have written for unit test and to mock is that
#Test
public void testCreateUser() {
Source scr = new Source();
//here i have mocked persistUser method
PowerMockito.when(v1.persistUser(Matchers.any(User.class))).thenReturn("value");
final String s = scr.createUser(new User());
Assert.assertEquals("value", s);
}
even if i have mocked persistUser method of GenUser v1 then also it did not return me "Value" as my return val.
thanks in adavanced.......:D
As in fge's comment:
All usages require #RunWith(PowerMockRunner.class) and #PrepareForTest annotated at class level.
Make sure you're using that test runner, and that you put #PrepareForTest(GenUser.class) on your test class.
(Source: https://code.google.com/p/powermock/wiki/MockitoUsage13)
Have a look at https://code.google.com/p/mockito/wiki/MockingObjectCreation - there are a couple of ideas there that may help you.
I don't know mockito, but if you don't mind using PowerMock and EasyMock, the following would work.
#Test
public void testCreateUser() {
try {
User u = new User();
String value = "value";
// setup the mock v1 for use
GenUser v1 = createMock(GenUser.class);
expect(v1.persistUser(u)).andReturn(value);
replay(v1);
Source src = new Source();
// Whitebox is a really handy part of PowerMock that allows you to
// to set private fields of a class.
Whitebox.setInternalState(src, "v1", v1);
assertEquals(value, src.createUser(u));
} catch (Exception e) {
// if for some reason, you get an exception, you want the test to fail
e.printStackTrack();
assertTrue(false);
}
}