简体   繁体   中英

Mockito: how to stub getter setter

I am kind of new to Mockito and I was wondering how I could stub a get/set pair.

For example

public interface Dummy {
     public String getString();
     public void setString(String string);
}

How can I make them behave properly: if somewhere in a test I invoke setString("something"); I would like getString() to return "something". Is that feasable or is there a better way to handle such cases?

I also wanted the getter to return the result of the recent setter-call.

Having

class Dog
{
    private Sound sound;

    public Sound getSound() {
        return sound;
    }
    public void setSound(Sound sound)   {
        this.sound = sound;
    }
}

class Sound
{
    private String syllable;

    Sound(String syllable)  {
        this.syllable = syllable;
    }
}

I used the following to connect the setter to the getter:

final Dog mockedDog = Mockito.mock(Dog.class, Mockito.RETURNS_DEEP_STUBS);
// connect getter and setter
Mockito.when(mockedDog.getSound()).thenCallRealMethod();
Mockito.doCallRealMethod().when(mockedDog).setSound(Mockito.any(Sound.class));

I can think of three possible approaches.

  1. Don't use HttpServletRequest directly in your application; make a wrapper class for it, and have an interface for the wrapper class. Wherever you currently use HttpServletRequest in the application, use the interface instead. Then in the test, have an alternative implementation of this interface. Then, you don't need a Mockito mock at all.

  2. Have a field in your test class that stores the value that you have set the String to. Make two Mockito Answer objects; one that returns the value of this field when getString is called, and another that sets the value of this field when setString is called. Make a mock in the usual way, and stub it to use both of these answers.

  3. Make an abstract class (which can be a static inner class of your test class) that implements the HttpServletRequest interface, but has the field that you want to set, and defines the getter and setter. Then mock the abstract class, and pass the Mockito.CALLS_REAL_METHODS in as a default answer. When you call the getter or the setter on the mock, the real method will kick in, which is the behaviour you want.

Hopefully, one of these three alternatives will meet your needs.

I've found that this works fine:

doAnswer(answer -> when(dummy.getString()).thenReturn((String) answer.getArguments()[0]))
    .when(dummy).setString(any());

I have to use the doAnswer(..).when(..) because the setter is a void method. When the setter is called with an object the getter will be set up to respond with the same object.

Very useful when you've got an interface, but no implementations.

In this particular case for HttpServletRequest stubbing I strongly recommend to use Spring-Mock framework: ( http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/mock/web/package-summary.html )

It has built-in mocks for web based operations.

Otherwise use the Answer to define your own response for your mocked objects ( http://mockito.googlecode.com/svn/branches/1.8.5/javadoc/org/mockito/stubbing/Answer.html )

I had this issue but didn't want to go with the accepted answer because doing so would cease the mocking of all getters and setters in my bean. All I wanted was to create stubs for a single getter/setter pair, not all. As such, I used the following code.

@Mock
private Dummy mockDummy;
private final MutableObject<String> stringWrapper = new MutableObject<>();

public TestClass() {
    MockitoAnnotations.initMocks(this);

    doAnswer(invocationOnMock -> {
        String injectedString = (String)invocationOnMock.getArguments()[0];
        TestClass.this.stringWrapper.setValue(injectedString);
        return null;
    }).when(this.mockDummy).setString(any());
    when(this.mockDummy.getString()).thenAnswer(
            invocationOnMock -> TestClass.this.stringValue.getValue());
}

The first lambda implements the Answer<Void> anonymous class' answer() method . Thus, whenever the setter method is executed by the code under test, this stub of that setter records it into the MutableObject helper object. This recorded value that was set can then be returned by the getter implementation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM