有什么办法可以替代动态方法吗?
假设我们有一个具有两个方法的接口:
public interface MyInterface {
public SomeType first();
public SomeType second();
}
该接口由 MyInterfaceImpl
实现。在实现内部,first()
调用 second()
来检索一些结果。
我想构建一个单元测试,它会根据 second()
的结果来断言 first()
的结果,类似于:
1 public class MyInterfaceTest {
2 private MyInterface impl = new MyInterfaceImpl();
4 @Test
5 public void testFirst() {
6 // modify behaviour of .second()
7 impl.first();
8 assertSomething(...);
10 // modify behaviour of .second()
11 impl.first();
12 assertSomethingElse(...);
13 }
14 }
有没有一种简单的方法在 2
行上创建一个模拟,以便直接调用对选定方法(例如 first()
)的所有调用(委托给 MyInterfaceImpl
)而其他一些方法(例如 second()
)被替换为模拟对应方法?
对于静态方法,这实际上可以通过 PowerMock 轻松实现,但对于动态方法,我需要类似的东西。
基于的解决方案
MyInterface mock = EasyMock.createMock(MyInterface.class);
MyInterface real = new MyInterfaceImpl();
EasyMock.expect(mock.first()).andReturn(real.first()).anyTimes();
EasyMock.expect(mock.second()).andReturn(_somethingCustom_).anyTimes();
还不够好,特别是对于具有大量方法(大量样板)的接口。我需要转发行为,因为 real
实际上取决于其他模拟。
我希望这样的事情由框架来处理,而不是由我自己的类来处理。这是可以实现的吗?
Let's say we have an interface which has two methods:
public interface MyInterface {
public SomeType first();
public SomeType second();
}
This interface is implemented by MyInterfaceImpl
. Inside the implementation, first()
calls second()
to retrieve some results.
I want to build a unit test which would assert things coming out of first()
based on what comes out of second()
, similar to:
1 public class MyInterfaceTest {
2 private MyInterface impl = new MyInterfaceImpl();
4 @Test
5 public void testFirst() {
6 // modify behaviour of .second()
7 impl.first();
8 assertSomething(...);
10 // modify behaviour of .second()
11 impl.first();
12 assertSomethingElse(...);
13 }
14 }
Is there an easy way to create a mock on the line 2
so that all calls to selected methods (e.g. first()
) would be invoked directly (delegated to MyInterfaceImpl
) whereas some other methods (e.g. second()
) replaced with mock counterparts?
This is actually very easily doable with PowerMock for static methods, but I need something similar for dynamic ones.
Solutions based on
MyInterface mock = EasyMock.createMock(MyInterface.class);
MyInterface real = new MyInterfaceImpl();
EasyMock.expect(mock.first()).andReturn(real.first()).anyTimes();
EasyMock.expect(mock.second()).andReturn(_somethingCustom_).anyTimes();
are not good enough, especially for interfaces having lots of methods (lots of boilerplate). I need the forwarding behaviour as real
actually depends on other mocks.
I would expect something like this to be handled by a framework, and not by my own class. Is this achievable?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
听起来你很可能应该为
first()
和second()
提供单独的接口,如果first()
的实现必须调用第二个()
。然后,您也可以拆分实现,并在测试first()
时模拟second()
。如果没有更具体的示例来说明first()
和second()
是什么,很难确定。在实现类上使用 EasyMock 来模拟仅
second()
调用可能有效,但您似乎无论如何都不想这样做。这可能需要告诉EasyMock将对first()
的调用传递给正常的实现 - 我不确定。另一种选择可能是在测试类中对实现进行子类化(作为嵌套类),从而允许您出于测试目的仅重写
second()
。虽然它非常丑陋。就我个人而言,我不喜欢仅仅为了测试其余部分而伪造课程的部分。我宁愿伪造一个类的所有依赖项。
It sounds like you should quite possibly have separate interfaces for
first()
andsecond()
, if the implementation offirst()
has to callsecond()
. You could then split the implementation too, and mock outsecond()
while testingfirst()
. Without a more concrete example of whatfirst()
andsecond()
are, it's tricky to say for sure.Using EasyMock on the implementation class to mock out only
second()
call might work, but you don't seem to want to do that anyway. This may require telling EasyMock to pass calls tofirst()
through to the normal implementation - I'm not sure.Another option might be to subclass the implementation within the test class (as a nested class) allowing you to override just
second()
for the purposes of testing. It's pretty ugly though.Personally I don't like faking out part of a class just to test the rest. I'd much rather fake out all a class's dependencies.
好的旧子类化怎么样?我的意思是
你没有测试你想要测试的确切类,而是一个匿名子类。但我们可以假设子类化在 Java 中工作正常。;-)
How about good old subclassing? I mean something like
You are not testing the exact class you want to test, but an anonymous subclass. But we can assume subclassing works ok in Java.;-)
也许您可以使用动态代理。
Possibly you could use a Dynamic Proxy.