Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2019/02/04/mockito-doreturn-vs-thenreturn #16

Open
utterances-bot opened this issue Aug 13, 2021 · 8 comments
Open

2019/02/04/mockito-doreturn-vs-thenreturn #16

utterances-bot opened this issue Aug 13, 2021 · 8 comments

Comments

@utterances-bot
Copy link

Mockito: doReturn vs thenReturn

In Mockito, you can specify what to return when a method is called. That makes unit testing easier because you don’t have to change existing classes. Mockito...

http://sangsoonam.github.io/2019/02/04/mockito-doreturn-vs-thenreturn.html

Copy link

I spy an instance from applicationContext, doreturn when(instance).someVoidMethod(),but I find someVoidMethod had been called;
tradeBasicServiceSpy = Mockito.spy(applicationContext.getBean(ITradeBasicService.class));
Mockito.doThrow(OvsBusinessCheckedException.class).doNothing().when(tradeBasicServiceSpy).updateStatusAndVersionCompareStatusAndVersionById(
Mockito.anyLong(), Mockito.anyString(), Mockito.anyString(), Mockito.anyByte());

Copy link
Owner

@asheCarry First of all, I think it better to call 'spy' on the object you want to monitor directly. You called 'spy' on applicationContext.getBean(ITradeBasicService.class) rather than applicationContext. You might have an issue because you spy on the result of getBean.

If you spy on applicationContext, you can return a mock object when getBean(ITradeBasicService.class) is called. That mock object can throw an exception, which you wanted to do.

// Mock Service
service = Mockito.mock(ITradeBasicService.class);
Mockito.doThrow(OvsBusinessCheckedException.class).doNothing().when(service).updateStatusAndVersionCompareStatusAndVersionById(Mockito.anyLong(), Mockito.anyString(), Mockito.anyString(), Mockito.anyByte());

// Spy
context = Mockito.spy(applicationContext);

// Spy returns Mock Service
Mockito.doReturn(service).when (context).getBean(ITradeBasicService.class);

Copy link

First,thanks for your answer.
My really question,I can not understand that when I use spy like #doReturn("foo").when(spy).get(0);# also throws IndexOutOfBoundsException ;
Now, I understand that Method of spy just adds proxy for the object from parameter,so when the object from parameter is a proxy essentially,doRetun().when(spyOfProxyObject).doSomething() also make A side effect.
So sorry for my lame English,I hope you can understand what I say;If you can,expect you can fix it。
Thanx again.

Copy link
Owner

@asheCarry
If the below code throws IndexOutOfBoundsException, I believe something is wrong.

doReturn("foo").when(spy).get(0);

Technically, this doesn't call the get method. This just configures what should be returned when get method with an argument 0 is called. By having this configure, this assertion passes. If there is no matched configuration, the method call hits the real implementation.

assertEquals("foo", spy.get(0));

Copy link

@SangsooNam
`
@test
public void spyTest() {
// realTarget
List list = new LinkedList();

    MyProxyList handler = new MyProxyList(list);
    ClassLoader loader = list.getClass().getClassLoader();
    Class[] interfaces = list.getClass().getInterfaces();
    // proxy target
    List proxy = (List) Proxy.newProxyInstance(loader, interfaces, handler);
    // spy proxy
    List spy = Mockito.spy(proxy);
    // will run get() then throw java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
    try{
        Mockito.doReturn("foo").when(spy).get(0);
    }catch (Exception e){
        Throwable cause = e.getCause().getCause();
        Assert.assertTrue(cause instanceof IndexOutOfBoundsException);
    }
}

class MyProxyList implements InvocationHandler {
    List target;

    MyProxyList(List target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return method.invoke(target, args);
    }
}

`
doReturn("foo").when(spy).get(0) will throw IndexOutOfBoundsException

Copy link

@SangsooNam
I resolved my problem by replace target object with the object come from spy;
So I can enjoy all functions from aop,and also not make relly rpc call method that I stub it

@SangsooNam
Copy link
Owner

@asheCarry
I don't have the full reason that you needed to spy the proxy. For the simple case, the below test works without throwing the exception.

@Test
public void doReturnWithSpyList() {
	List list = new LinkedList<String>();
	List spy = Mockito.spy(list);

	// This doesn't throw IndexOutOfBoundsException
	Mockito.doReturn("foo").when(spy).get(0);

	Assert.assertEquals("foo", spy.get(0));
}

And, when I run your test, it doesn't work and fails with Mockito cannot mock/spy because : final class. Maybe there is some other thing and I wanted to share my runs.

Screen Shot 2021-08-18 at 2 03 14 PM

Copy link

@SangsooNam
InvocationHandler the full name is org.springframework.cglib.proxy.InvocationHandler;
I heared can mock or spy final class on higher version of Mockito,just heared but not test it;
The primary reason of I want to spy a proxy instance is that which code is needed to be tested uses proxy instance not origin object . Proxy intance can enhance origin object, like adding transaction for some method by use annotation @transaction

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants