mockito verify method call inside method - java

for a unit tests i am trying to verify if there is
a way to verify a method call inside a method with mockito verify?
An example would be:
public delete(param) {
VideoService.deleteVideo(param); << i want to verify the call of this method
return etc..
}
I can check if delete is called with :
verify(mock,times(1)).delete(param);
Is there also like a way to check the inside method like:
verify(mock,times(1)).delete(param).VideoService.deleteVideo(param);

You can use a spy.
public class MyVideoService {
private VideoService videoService;
public MyVideoService(VideoService videoService) {
this.videoService = videoService;
}
public void delete(String param) {
videoService.deleteVideo(param);
}
}
public class VideoService {
public void deleteVideo(String param) {
}
}
If you now want to test an object that uses MyVideoService. E.g.
public class ObjectThatUsesMyVideoService {
private MyVideoService myVideoService;
ObjectThatUsesMyVideoService(MyVideoService myVideoService) {
this.myVideoService = myVideoService;
}
public void deleteVideo(String param) {
myVideoService.delete(param);
}
}
You can write a test like this
public class MyVideoServiceTest {
#Test
public void delete(){
// VideoService is just a mock
VideoService videoServiceMock = Mockito.mock(VideoService.class);
// Creating the real MyVideoService
MyVideoService myVideoService = new MyVideoService(videoServiceMock);
// Creating a spy proxy
MyVideoService myVideoServiceSpy = Mockito.spy(myVideoService);
ObjectThatUsesMyVideoService underTest = new ObjectThatUsesMyVideoService(myVideoServiceSpy);
underTest .deleteVideo("SomeValue");
// Verify that myVideoService was invoked
Mockito.verify(myVideoServiceSpy, Mockito.times(1)).delete("SomeValue");
// Verify that myVideoService invoked the VideoService
Mockito.verify(videoServiceMock, Mockito.times(1)).deleteVideo("SomeValue");
}
}

Lets assume you have a class
class MyVideoService {
final VideoService videoService;
public MyVideoService(VideoService videoService) {
this.videoService = videoService;
}
public void delete(param) {
videoService.deleteVideo(param);
}
}
Then you mock VideoService with
VideoService videoService = mock(VideoService.class);
And create MyVideoService with this mocked instance, call method, verify:
MyVideService myVideoService = new MyVideoService(videoService);
myVideoService.delete (param);
verify(videoService, times(1)).deleteVideo(param);

Related

Mockito, MissingMethodInvocationException when run all tests in class

Here is my test class.
#ExtendWith(MockitoExtension.class)
class DishServiceTest {
static MockedStatic<DaoFactory> daoFactoryDummy;
static MockedStatic<FileUtil> fileUtilDummy;
#Mock
DaoFactory daoFactory;
#Mock
DishDao dishDao;
#Spy
DishService dishService;
#BeforeAll
static void setUp() {
fileUtilDummy = Mockito.mockStatic(FileUtil.class);
daoFactoryDummy = Mockito.mockStatic(DaoFactory.class);
}
#AfterAll
static void close() {
daoFactoryDummy.close();
fileUtilDummy.close();
}
#Test
void deleteWithImage_id0_success() {
daoFactoryDummy.when(ServiceManager::getInstance).thenReturn(daoFactory);
when(daoFactory.createDishDao()).thenReturn(dishDao);
long id = 2;
String deleteDir = "/dish-image/2";
dishService.deleteWithImage(id, deleteDir);
verify(dishDao, times(1)).delete(id);
fileUtilDummy.verify(() -> FileUtil.deleteDishFolder(deleteDir));
}
#Test
void update_idSet_success() {
daoFactoryDummy.when(ServiceManager::getInstance).thenReturn(daoFactory);
when(daoFactory.createDishDao()).thenReturn(dishDao);
Dish dish = new Dish(2, "testName",
"testDescription", Category.DRINKS, BigDecimal.TEN, "/image21");
dishService.saveOrUpdate(dish);
verify(dishDao, times(1)).update(dish);
verify(dishDao, times(1)).close();
}
}
I mock static methods like this because DishService class gets dao object from DaoFactory.
Here is an example of DishService method
public class DishService {
public void saveOrUpdate(Dish newDish) {
try (DishDao dishDao = DaoFactory.getInstance().createDishDao()) {
long newDishId = newDish.getId();
if (newDishId == 0) {
dishDao.save(newDish);
} else {
dishDao.update(newDish);
}
}
}
}
And of DaoFactory
public class JDBCDaoFactory extends DaoFactory {
DBManager dbManager = DBManager.getInstance();
UserDaoMapper userDaoMapper = new UserDaoMapper();
DishDaoMapper dishDaoMapper = new DishDaoMapper();
OrderDaoMapper orderDaoMapper = new OrderDaoMapper();
OrderItemDaoMapper orderItemDaoMapper = new OrderItemDaoMapper();
#Override
public UserDao createUserDao() {
return new JDBCUserDao(dbManager.getConnection(),
userDaoMapper);
}
#Override
public DishDao createDishDao() {
return new JDBCDishDao(dbManager.getConnection(), dishDaoMapper);
}
#Override
public OrderDao createOrderDao() {
return new JDBCOrderDao(dbManager.getConnection(), orderDaoMapper,
orderItemDaoMapper);
}
}
And here is the exception I have
org.mockito.exceptions.misusing.MissingMethodInvocationException:
Also, this error might show up because:
you stub either of: final/private/equals()/hashCode() methods. Those methods cannot be stubbed/verified. Mocking methods
declared on non-public parent classes is not supported.
inside when() you don't call method on mock but on some other object. at
service.DishServiceTest.update_idSet_success(DishServiceTest.java:61)
Here is the line 61
The strangest thing here is that tests pass when I run them seperately, but if i press run all tests in class I get the exception above.

mocking a recursive class

using Spring 2.0.3.RELEASE, JUnit Jupiter 5.7.0, Mockito 3.3.3
try to test method method01 of class Class01:
public class Class01 {
private RestConnector con;
public Class01(){
con = RestConnector.getInstance();
}
public Response method01(String x) {
Class01 example = new Class01();
String x = example.isAuthenticated();
// more stuff after this
}
public String isAuthenticated() throws IOException {
// I do stuff
return "a string";
}
}
In the test class have tried
public class Class01Test{
#Mock private Class01 class01Mock;
#Spy #InjectMocks private Class01 class01;
#Test
public void test() throws Throwable {
doReturn("I returned").when(class01). ??? stuck here .. always goes into the isAuthenticated method
Response result = class01.method01("a string");
}
}
Currently the test is always running the real method isAuthenticated.
How to setup a mock for the field example in method method01 so that the execute skips going into method isAuthenticated?
try to test method method01 of class Class01
Then you don't need mocks.
#Test
public void test() throws Throwable {
Class01 c = new Class01();
Response expected = ... ;
assertEquals(c.method01("input"), expected);
}
If you want to inject behaviour into example variable, you need to move it to a field
public class Class01 {
private RestConnector con;
private Class01 inner;
public Class01(){
con = RestConnector.getInstance();
}
Class01(Class01 c) {
this();
this.inner = c;
}
public Response method01(String x) {
String x = inner.isAuthenticated();
// more stuff after this
}
Along with a Mock
#RunWith(MockitoJunitRunner.class)
public class Class01Test{
#Mock Class01 class01Mock;
#Test
public void test() throws Throwable {
Response expected = ... ;
when(class01Mock.isAuthenticated()).thenReture(expected); ... // TODO: Setup
Class01 c = new Class01(class01Mock); // pass in the mock
assertEquals(c.method01("input"), expected);
}
However, unclear why you need a nested object of the same class when you appear to only need this.isAuthenticated()
Ideally, you'd also mock the RestConnector

How to inject mocks into a class that has 1 constructor with parameters?

I have the following class (Condensed it to focus on issue instead of showing entire class):
#Component
public class ABCDEF {
private final Helper helper;
private final URI uri;
public ABCDEF(Helper helper, #Value("${endpoint.url}") URI uri) {
this.helper = helper;
this.uri = uri;
}
public void b(){
helper.toString();
}
}
For its test, I am looking to inject the mocks as follows but it is not working.
The helper comes up as null and I end up having to add a default constructor to be able to throw the URI exception.
Please advice a way around this to be able to properly inject the mocks. Thanks.
#RunWith(JUnitMockitoRunner.class)
public class ABCDEFTest {
#Mock
private Helper helper;
#InjectMocks
private ABCDEF abcdef = new ABCDEF(
helper,
new URI("test")
);
// adding just to be able to throw Exception
public ABCDEFTest() throws URISyntaxException {
}
#Test
public void b() {
abcdef.b();
}
}
Note: Using Mockito version 1.10.19. Will need to stick to this version.
This should work:
#RunWith(MockitoJUnitRunner.class)
public class ABCDEFTest {
#Mock
private Helper helper;
private ABCDEF abcdef;
#Before
public void setUp() throws URISyntaxException {
abcdef = new ABCDEF(
helper,
new URI("test")
);
}
#Test
public void b() {
abcdef.b();
}
}
Or, instead of using #RunWith, you can initialize mock inside setUp method:
public class ABCDEFTest {
private Helper helper;
private ABCDEF abcdef;
#Before
public void setUp() throws URISyntaxException {
helper = Mockito.mock(Helper.class);
abcdef = new ABCDEF(
helper,
new URI("test")
);
}
#Test
public void b() {
abcdef.b();
}
}

How to verify a method was called inside another method with Mockito

I'm fairly new to Mockito, and I've been looking for a way to verify that if I call the filter() method with the right string, that the foo method will get called once.
public class A
{
private final Config _config;
public A(Config config) { _config = config; }
public void filter(String str)
{
if(str.startsWith("a"))
{
if(str.contains("z"))
{
foo(config.getName());
}
}
}
private void foo(String bar)
{
(...)
}
}
Here is my current code:
#Test
public void testOne()
{
Config config = new Config(configFile);
A a = Mockito.spy(new A(config));
a.filter("abcz");
verify(a, times(1)).foo(someString);
}
Try to be more generic while such a test. If you don't need to specify what exactly argument should by passed then just use any():
import static org.mockito.ArgumentMatchers.any;
verify(a).foo(any(String.class));

Verify mock invocation only in specific code block, igoring other calls

I have this (simplified) service class:
public interface EventListener {
void call();
}
public class MyService {
private final EventListener eventListener;
private final List<String> elements = new LinkedList<>();
public MyService(EventListener eventListener) {
this.eventListener = eventListener;
}
public void addElement(String element) {
elements.add(element);
eventListener.call();
}
public void removeElement(String element) {
elements.remove(element);
eventListener.call();
}
}
And this test method:
#Test
public void remove_should_call_event_listener() {
// arrange
EventListener eventListener = Mockito.mock(EventListener.class);
MyService myService = new MyService(eventListener);
myService.addElement("dummy");
// act
myService.removeElement("dummy");
// assert
Mockito.verify(eventListener).call();
}
How can I tell Mockito to ignore calls of eventListener.call() during "arrange" and verify only calls during "act"? I want to verify that eventListener.call() was called during myService.removeElement(...) and ignore all other calls.
Just before acting, call:
Mockito.reset(eventListener); // resets the set-up also
or
Mockito.clearInvocations(eventListener) // resets only the invocation history

Categories

Resources