简体   繁体   English

Mockito:如何存根 getter setter

[英]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.我对 Mockito 有点陌生,我想知道如何存根 get/set 对。

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");我怎样才能让它们正常运行:如果在测试中的某个地方我调用了setString("something"); I would like getString() to return "something".我希望getString()返回“某物”。 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.我还希望 getter 返回最近的 setter 调用的结果。

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:我使用以下方法将 setter 连接到 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;不要在你的应用程序中直接使用HttpServletRequest 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.无论您当前在应用程序中的何处使用HttpServletRequest ,请改用该接口。 Then in the test, have an alternative implementation of this interface.然后在测试中,有这个接口的替代实现。 Then, you don't need a Mockito mock at all.然后,您根本不需要 Mockito 模拟。

  2. Have a field in your test class that stores the value that you have set the String to.在您的测试类中有一个字段,用于存储您为String设置的值。 Make two Mockito Answer objects;制作两个 Mockito Answer对象; 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.一个在调用getString时返回该字段的值,另一个在调用setString时设置该字段的值。 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.创建一个抽象类(它可以是您的测试类的静态内部类),它实现了HttpServletRequest接口,但具有您要设置的字段,并定义了 getter 和 setter。 Then mock the abstract class, and pass the Mockito.CALLS_REAL_METHODS in as a default answer.然后模拟抽象类,并将 Mockito.CALLS_REAL_METHODS 作为默认答案传入。 When you call the getter or the setter on the mock, the real method will kick in, which is the behaviour you want.当你在 mock 上调用 getter 或 setter 时,真正的方法将启动,这就是你想要的行为。

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.我必须使用 doAnswer(..).when(..) 因为 setter 是一个 void 方法。 When the setter is called with an object the getter will be set up to respond with the same object.当 setter 被一个对象调用时,getter 将被设置为以相同的对象响应。

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 )在 HttpServletRequest 存根的这种特殊情况下,我强烈建议使用 Spring-Mock 框架:( http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/mock/web/package-摘要.html )

It has built-in mocks for web based operations.它具有用于基于 Web 的操作的内置模拟。

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 )否则,请使用 Answer 为您的模拟对象定义您自己的响应 ( 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.我有这个问题,但不想接受已接受的答案,因为这样做会停止嘲笑我的 bean 中的所有getter 和 setter。 All I wanted was to create stubs for a single getter/setter pair, not all.我想要的只是为单个 getter/setter 对创建存根,而不是全部。 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 .第一个 lambda 实现了Answer<Void>匿名类的answer()方法 Thus, whenever the setter method is executed by the code under test, this stub of that setter records it into the MutableObject helper object.因此,每当被测代码执行 setter 方法时,该 setter 的存根会将其记录到MutableObject帮助程序对象中。 This recorded value that was set can then be returned by the getter implementation.设置的这个记录值然后可以由 getter 实现返回。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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