java-与Mockito的接口的模拟getter / setter方法

我试图用jUnit和Mockito测试我的实现,但是遇到了问题.这是一个非常简单的示例,解释了该问题

接口KeyValueInterface

public interface KeyValueInterface {

    public abstract String getKey();

    public abstract void setKey(String key);

    public abstract String getValue();

    public abstract void setValue(String value);

}

类KeyValueImpl

public class KeyValueImpl implements KeyValueInterface {

    private String key;
    private String value;

    @Override
    public String getKey() {
        return key;
    }

    @Override
    public void setKey(String key) {
        this.key = key;
    }

    @Override
    public String getValue() {
        return value;
    }

    @Override
    public void setValue(String value) {
        this.value = value;
    }

}

具有“业务逻辑”的类

public class ValueFinder {

    public KeyValueInterface findValueForKey(KeyValueInterface keyValue){
        keyValue.setValue("foo");
        return keyValue;
    }

}

jUnit测试类

import static org.junit.Assert.*;

import org.junit.Test;
import org.mockito.Mockito;

public class ValueFinderTest {

    @Test
    public void testNotMocked() {
        KeyValueInterface keyValue = new KeyValueImpl();
        keyValue = (new ValueFinder()).findValueForKey(keyValue);
        assertEquals("foo", keyValue.getValue()); // works fine
    }

    @Test
    public void testMocked1() {
        KeyValueInterface keyValue = Mockito.mock(KeyValueInterface.class);
        keyValue = (new ValueFinder()).findValueForKey(keyValue);
        assertEquals("foo", keyValue.getValue()); // java.lang.AssertionError:
                                                    // expected:<foo> but
                                                    // was:<null>

    }

    @Test
    public void testMocked2() {
        KeyValueInterface keyValue = Mockito.mock(KeyValueInterface.class);
        keyValue = (new ValueFinder()).findValueForKey(keyValue);
        Mockito.when(keyValue.getValue()).thenCallRealMethod();
        Mockito.doCallRealMethod().when(keyValue).setValue(Mockito.any(String.class));
        assertEquals("foo", keyValue.getValue()); // org.mockito.exceptions.base.MockitoException:
                                                    // Cannot call real method
                                                    // on java interface.
                                                    // Interface does not have
                                                    // any implementation!
                                                    // Calling real methods is
                                                    // only possible when
                                                    // mocking concrete classes.

    }

}

我的探究是,出于技术原因,我需要模拟KeyValue,这超出了我的控制范围.因此,我不能只使用方法testNotMocked().同样由于技术原因,我不得不控制接口(而不是类).

有什么办法可以做到这一点?

非常感谢.

解决方法:

如果要编写要测试的方法的javadoc,甚至不知道接口的任何方法在做什么,则应编写以下代码:

/**
 * Sets "foo" as the value of the given keyValue, and returns it
 */

您甚至不应该假设getValue()返回之前设置的值.这当然不是模拟将要执行的操作,因为模拟除了您要执行的操作外不会执行任何其他操作.您要做的只是测试方法的约定,而无需假设接口的实现.所以你的测试应该是

@Test
public void testMocked1() {
    KeyValueInterface keyValue = Mockito.mock(KeyValueInterface.class);
    KeyValueInterface result = (new ValueFinder()).findValueForKey(keyValue);

    // tests that the value has been set to "foo"
    verify(keyValue).setValue("foo");

    // tests that the method returns its argument
    assertSame(keyValue, result);
}
上一篇:java-春季测试-注入具有嵌套bean依赖项的模拟bean


下一篇:java-Mockito使用模拟对象测试DAO