使用 EasyMock 模拟使用 jni 的对象

发布于 2024-10-09 02:36:59 字数 644 浏览 5 评论 0原文

因此,我的待测类的代码看起来非常像这样,

public void doSomething(int param)
{
    Report report = new Report()
    ...do some calculations
    report.someMethod(someData)
}

我的目的是将报告的构造提取到受保护的方法中,并覆盖它以使用模拟对象,然后我可以测试该对象以确保使用正确的数据调用了 someMethod。

到目前为止,一切都很好。但 Report 不受我的控制,更糟糕的是它使用 JNI 在运行时加载库。

如果我这样做 Report report = EasyMock.createMock(Report.class)

然后 EasyMock 尝试使用反射来找出类成员,但这会导致尝试加载 JNI 库,但失败(JNI 库仅在 UNIX 上可用)。

我正在考虑两件事:a)引入具有两个实现的 ReportWrapper 接口,其中一个将委托对真实报表(因此基本上是代理)的调用,第二个将基本上使用模拟对象。或者 b)不调用 someMethod,而是调用受保护的方法,该方法将依次调用我可以在测试子类中重写的 someMethod。

不管怎样,看起来都很恶心。还有更好的办法吗?

So my class under test has code that looks braodly like this

public void doSomething(int param)
{
    Report report = new Report()
    ...do some calculations
    report.someMethod(someData)
}

my intention was to extract the construction of report into a protected method and override it to use a mock object that I could then test to ensure that someMethod had been called with the right data.

So far so good. But Report isnt under my control, and to mkae things worse it uses JNI to load a library at runtime.

If I do
Report report = EasyMock.createMock(Report.class)

then EasyMock attempts to use reflection to find out the class members, but this causes an attempt to load the JNI library, which fails (the JNI libraries are only available on UNIX).

Im considering two things: a) Introduce a ReportWrapper interface with two implementations, one of which will delegate calls to an real Report (so basically a Proxy), and a second which will basically use a mock object. or b) instead of calling someMethod, call a protected method which will in turn call someMethod that I can override in a testing subclass.

Either way it seems nasty. Any better ways?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

北渚 2024-10-16 02:36:59

如果没有 Report 类的接口,那么您建议的包装器是正确的方法。
“重构:改进现有代码的设计”这本书有一章关于从设计糟糕的类中提取接口。

如果您使用某些 DI 框架(例如 SpringFramework),您可以轻松地用某些 ObjectFactory 替换该对象来创建正确的实现(模拟与真实的实现)。

If there's no interface to Report class, then your suggested wrapper is the correct approach.
The book "Refactoring: Improving the Design of Existing Code" has a chapter about extracting interfaces from badly designed classes.

If you're using some DI framework (e.g. SpringFramework) you can easily replace this object with some ObjectFactory to create the correct implementation (mock vs. real one).

乄_柒ぐ汐 2024-10-16 02:36:59

使用 EasyMock,您将不得不诉诸某种形式的重构。避免这种情况的唯一方法是使用可以模拟内部创建的对象的模拟工具。使用JMockit(我开发的工具),测试可以这样编写:

public void testDoSomething(final Report mockedReport)
{
    // create "someData"

    objectUnderTest.doSomething(123);

    new Verifications() {{ mockedReport.someMethod(someData); }};
}

With EasyMock, you would have to resort to some form of refactoring. The only way to avoid it would be to use a mocking tool which can mock internally created objects. With JMockit (a tool I develop), the test could be written like this:

public void testDoSomething(final Report mockedReport)
{
    // create "someData"

    objectUnderTest.doSomething(123);

    new Verifications() {{ mockedReport.someMethod(someData); }};
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文