Java 使用JMockIt模拟简单属性访问
我有一个简单的获取集界面:Java 使用JMockIt模拟简单属性访问,java,unit-testing,properties,mocking,jmockit,Java,Unit Testing,Properties,Mocking,Jmockit,我有一个简单的获取集界面: public interface Foo { void setBaz(String baz); String getProcessedBaz(); } 这个接口是我的实际测试类的依赖项。我试图模仿Foo来实现这种有效的行为: public class MockedFoo implements Foo { private String bazField; @Override public void setBaz(
public interface Foo {
void setBaz(String baz);
String getProcessedBaz();
}
这个接口是我的实际测试类的依赖项。我试图模仿
Foo
来实现这种有效的行为:
public class MockedFoo implements Foo {
private String bazField;
@Override
public void setBaz(String baz) {
bazField = baz;
}
@Override
public String getProcessedBaz() {
return "PROCESSED_" + bazField;
}
}
因此,我的预期结果是:
mockedFoo.setBaz("ABC");
assertEquals("PROCESSED_ABC", mockedFoo.getProcessedBaz());
我能够在
验证
中使用with capture
捕获方法参数,但是如何使用相同的输入值设置期望
?看来你要么能做,要么能做
有没有办法用JMockIt来表达这一点?我使用的是最新版本(1.9)
注意:我知道我可以简单地设置一个
实体模型
实例并输入上面的所有代码。然而,我真正的代码要复杂得多,我不想手工制作整个模拟类。编写这种基于状态的测试的一种方法是:
public interface Foo {
void setBaz(String baz);
String getProcessedBaz();
void someOtherMethod();
}
public static class ClassUnderTest {
String doSomething(Foo foo) {
foo.setBaz("ABC");
foo.someOtherMethod();
return foo.getProcessedBaz();
}
}
@Test
public void mockFoo() {
Foo foo = new MockUp<Foo>() {
String baz;
@Mock void setBaz(String baz) { this.baz = baz; }
@Mock String getProcessedBaz() { return "PROCESSED_" + baz; }
}.getMockInstance();
String res = new ClassUnderTest().doSomething(foo);
assertEquals("PROCESSED_ABC", res);
}
公共接口Foo{
void setBaz(字符串baz);
字符串getProcessedBaz();
void someOtherMethod();
}
测试中的公共静态类{
字符串doSomething(Foo-Foo){
foo.setBaz(“ABC”);
foo.someOtherMethod();
返回foo.getProcessedBaz();
}
}
@试验
公共文件(mockFoo){
Foo-Foo=新模型(){
字符串baz;
@Mock void setBaz(字符串baz){this.baz=baz;}
@模拟字符串getProcessedBaz(){返回“已处理的”+baz;}
}.getMockInstance();
String res=new ClassUnderTest().doSomething(foo);
资产质量(“已处理的”资产);
}
同样的测试也可以使用JMockit Expectations API(使用
委托
对象)编写,但由于该API用于基于行为的测试(即,当您更关心调用哪些方法而不是对象之间的状态传输时),测试将更加详细。您可以使用委托来完成此操作。你可以试试这个
要测试的类
public interface Foo {
void setBaz(String baz);
String getProcessedBaz();
}
class FooSubClass implements Foo {
private String bazField;
@Override
public void setBaz(String baz) {
bazField = null;
}
@Override
public String getProcessedBaz() {
return bazField;
}
}
测试班
import mockit.Capturing;
import mockit.Deencapsulation;
import mockit.Delegate;
import mockit.NonStrictExpectations;
import org.junit.Before;
import org.junit.Test;
public class FooTest
{
FooSubClass fooSubClass;
@Capturing Foo fooMocked;
@Before
public void setUp()
{
fooSubClass = new FooSubClass();
}
@Test
public void testAMethod()
{
new NonStrictExpectations()
{
{
fooMocked.setBaz(anyString);
result = new Delegate()
{
void setBaz(String baz)
{
Deencapsulation.setField(fooSubClass, "bazField", baz);
}
};
times = 1;
fooMocked.getProcessedBaz();
result = new Delegate()
{
String getProcessedBaz()
{
return "PROCESSED_" + Deencapsulation.getField(fooSubClass, "bazField");
}
};
times = 1;
}
};
fooSubClass.setBaz("abc");
System.out.println(fooSubClass.getProcessedBaz());
}
}
注意:这是从Varun的答案中得到启发的,但我希望避免使用反射和中间类。Rogério也提供了一个可行的替代方案,但它不适合我测试的总体结构。多亏了这两个
以下是我最终让它工作的方式:
public interface Foo {
void setBaz(String baz);
String getProcessedBaz();
}
@RunWith(JMockit.class)
public class FooTest {
@Injectable
private Foo mockedFoo = null;
@Test
public void testBaz() {
new Expectations() {
private String bazState; // Variable inside Expectations stores the state between calls
{
mockedFoo.setBaz(anyString);
result = new Delegate() {
void setBaz(String baz) { bazState = baz; }
};
mockedFoo.getProcessedBaz();
result = new Delegate() {
String getProcessedBaz() { return "PROCESSED_" + bazState; }
};
}
};
mockedFoo.setBaz("ABC");
assertEquals("PROCESSED_ABC", mockedFoo.getProcessedBaz());
}
}
谢谢@Rogério。事实上,我今天使用的是
Mockup
(见我问题的结尾)。与显式创建模拟类相比,这种方法似乎没有任何优势。我正在寻找(希望)更紧凑的方法。:)那么您不需要模拟的方法呢,比如上面示例中的someOtherMethod
?我相信这是一个优势。也就是说,我同意对于方法很少的接口来说,创建一个常规的实现类更简单。我明白了,是的,这绝对是一个优势。我希望用更简单的语法得到更多的答案。如果没有,我将只使用模型
。