我有一个简单的get-set接口:
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());
我能够在withCapture
中使用Verification
捕获方法参数,但如何设置具有相同输入值的Expectation
?看来你可以做其中一个。
有没有办法在JMockIt中表达这一点?我使用的是最新版本(1.9)。
注意:我知道我可以简单地设置一个Mockup<Foo>
实例并输入上面的所有代码。但是,我的真实代码要复杂得多,我宁愿不用手工制作整个模拟类。
答案 0 :(得分:1)
您可以使用Delegate执行此操作。你可以试试这个
要测试的课程
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());
}
}
答案 1 :(得分:1)
注意:这是受到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());
}
}
答案 2 :(得分:0)
编写这种基于状态的测试的一种方法是:
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);
}
也可以使用JMockit Expectations API(使用Delegate
对象)编写等效测试,但由于该API用于基于行为的测试,因此它将更加冗长(即,当你更关心调用哪些方法而不是对象之间的状态转移时。)