如何测试使用查找的 NetBeans 平台代码?
How to test NetBeans Platform code which uses Lookups?
TL;DR 如何为使用静态方法查找依赖项的 NetBeans 平台代码编写单元测试?
在 NetBeans 平台应用程序中,我遇到了这样的代码:
MyService service = Lookup.getDefault().lookup(MyService.class);
service.doStuff(....);
对我来说,静态访问似乎是一种反模式并且难以测试。当我 Google 周围时,我只找到关于低耦合和高内聚、远程接口等的评论。
很多人似乎 think this is a Good Idea 但我想知道如何为这样的代码编写合理的单元测试,而不诉诸模拟静态方法或在我的单元测试中使用查找功能。
我想到的第一个想法是将查找重构为常规依赖项:
public class MyClass {
private Lookup lookup = Lookup.getDefault();
public void myMethod() {
MyService service = lookup.lookup(MyService .class);
service.doStuff(....);
}
public void setLookup(Lookup lookup) {
this.lookup = lookup;
}
然后使用 setter 提供模拟 Lookup 进行测试。
这会起作用,但仍然会导致测试代码在设置模拟之前调用 Lookup.getDefault()
。 Netbeans Platform 没有提供常规的依赖注入机制,所以如果我这样引入它,感觉就像逆流而上。
我觉得我错过了什么。是否有为 Netbeans 平台代码编写单元测试的标准方法?
到目前为止,我找到了几种解决方法。
1 - 在 Lookup 中发布 class 的测试版本,位置更高
@org.openide.util.lookup.ServiceProvider(service = MyService.class, position = 1)
public class TestService implements MyService {
public void doStuff(....) {
2 - 使用 NBJunit 的 MockService
public class MyTest extends NbTestCase {
public void setUp() throws Exception {
org.netbeans.junit.MockServices.setServices(TestService.class);
}
3- 注册您自己的查找实现:
static {
System.setProperty("org.openide.util.Lookup", TestLookup.class.getName());
}
public class TestLookup extends org.openide.util.lookup.AbstractLookup {
public TestLookup() {
this(new org.openide.util.lookup.InstanceContent());
}
private TestLookup(org.openide.util.lookup.InstanceContent ic) {
super(ic);
ic.add(new TestService());
}
其中一些想法是在此处找到的:https://openide.netbeans.org/tutorial/test-patterns.html。
class TestService 必须在您的测试中可见 class(通常,我们使用 Lookup 来降低依赖性,这就是接口和实现位于不同模块中的原因)。
考虑在你的测试模块的独立性中加入TestService这个模块。
TL;DR 如何为使用静态方法查找依赖项的 NetBeans 平台代码编写单元测试?
在 NetBeans 平台应用程序中,我遇到了这样的代码:
MyService service = Lookup.getDefault().lookup(MyService.class);
service.doStuff(....);
对我来说,静态访问似乎是一种反模式并且难以测试。当我 Google 周围时,我只找到关于低耦合和高内聚、远程接口等的评论。
很多人似乎 think this is a Good Idea 但我想知道如何为这样的代码编写合理的单元测试,而不诉诸模拟静态方法或在我的单元测试中使用查找功能。
我想到的第一个想法是将查找重构为常规依赖项:
public class MyClass {
private Lookup lookup = Lookup.getDefault();
public void myMethod() {
MyService service = lookup.lookup(MyService .class);
service.doStuff(....);
}
public void setLookup(Lookup lookup) {
this.lookup = lookup;
}
然后使用 setter 提供模拟 Lookup 进行测试。
这会起作用,但仍然会导致测试代码在设置模拟之前调用 Lookup.getDefault()
。 Netbeans Platform 没有提供常规的依赖注入机制,所以如果我这样引入它,感觉就像逆流而上。
我觉得我错过了什么。是否有为 Netbeans 平台代码编写单元测试的标准方法?
到目前为止,我找到了几种解决方法。
1 - 在 Lookup 中发布 class 的测试版本,位置更高
@org.openide.util.lookup.ServiceProvider(service = MyService.class, position = 1)
public class TestService implements MyService {
public void doStuff(....) {
2 - 使用 NBJunit 的 MockService
public class MyTest extends NbTestCase {
public void setUp() throws Exception {
org.netbeans.junit.MockServices.setServices(TestService.class);
}
3- 注册您自己的查找实现:
static {
System.setProperty("org.openide.util.Lookup", TestLookup.class.getName());
}
public class TestLookup extends org.openide.util.lookup.AbstractLookup {
public TestLookup() {
this(new org.openide.util.lookup.InstanceContent());
}
private TestLookup(org.openide.util.lookup.InstanceContent ic) {
super(ic);
ic.add(new TestService());
}
其中一些想法是在此处找到的:https://openide.netbeans.org/tutorial/test-patterns.html。
class TestService 必须在您的测试中可见 class(通常,我们使用 Lookup 来降低依赖性,这就是接口和实现位于不同模块中的原因)。
考虑在你的测试模块的独立性中加入TestService这个模块。