java - 如何调用指示应该在实例上调用什么方法的传递参数
问题描述
在我的测试中,我有很多类似的东西:
try{
someInstance.someMethod(argument)
}catch(Exception e){
// assert exception message
}
我想为此创建方法,但是如何?我如何传递应该在特定实例上调用的方法?
我试过了
private <String,R> void runCommandWithExpectedError(Function<String,R> fnc, String argument, String errorMessage){
try {
fnc.apply(argument);
} catch (Exception e) {
Assert.assertThat(e.getMessage(), Matchers.equalTo(errorMessage));
}
}
但是它抱怨不能从静态上下文中引用非静态方法。像这样称呼它时
runCommandWithExpectedError(ChannelSftp::rm,"path","No such file or directory");
此外,该方法无法知道它应该在哪个实例上调用该方法,这样可能吗?
谢谢!
解决方案
一般性发言
我不会这样做来简化我的单元测试。单元测试应该测试代码的每个组件,并且应该易于阅读和修改。让它们保持这样,即使它们听起来重复,这就是你的代码的工作方式,我希望有一个简单的测试,它看起来像所有其他的,但很容易显示它的作用。
访客模式
如果您真的想这样做,可以使用访问者设计模式来完成。
想象一下,你有两个这样的类:
public class Class1 {
public int method1(String string) {
return string.contains("something") ? 2 : 3;
}
}
public class Class2 {
public double method2(String string) {
return string.contains("something") ? 3.0 : 4.0;
}
}
您的测试如下所示:
@Test
public void test1() {
Class1 class1 = new Class1();
int result = class1.method1("something");
//...assertions
}
@Test
public void test2() {
Class2 class2 = new Class2();
double result = class2.method2("else");
//...assertions
}
如果我的理解是正确的,您宁愿使用单个方法测试对该方法的调用并最终捕获异常以测试其消息。
Visitor
首先,为要测试的每种类型创建一个接口:
public interface Visitor {
int visit(Class1 class1, String argument);
double visit(Class2 class2, String argument);
}
然后,您创建一个Visitable
接受Visitor
类型的接口:
public interface Visitable {
public void accept(Visitor visitor, String argument);
}
一旦你这样做了,你应该让你想要测试的类实现Visitable
接口(基本上让它们被“访问者”“访问”):
public class Class1 implements Visitable {
public int method1(String string) {
return string.contains("something") ? 2 : 3;
}
@Override
public void accept(Visitor visitor, String argument) {
visitor.visit(this, argument);
}
}
public class Class2 implements Visitable {
public double method2(String string) {
return string.contains("something") ? 3.0 : 4.0;
}
@Override
public void accept(Visitor visitor, String argument) {
visitor.visit(this, argument);
}
}
现在,您可以创建一个TestVisitor
实现Visitor
接口并执行您希望的操作的类:
public class TestVisitor implements Visitor {
@Override
public int visit(Class1 class1, String argument) {
return class1.method1(argument);
}
@Override
public double visit(Class2 class2, String argument) {
return class2.method2(argument);
}
}
因此,可以通过执行操作的单个测试来重构您的单元测试:
private final Visitor TEST_VISITOR = new TestVisitor();
private void sharedTestMethod(Visitable instance, String argument) {
instance.accept(TEST_VISITOR, argument);
}
您的测试只需创建实例然后调用sharedTestMethod
:
@Test
public void test1() {
Class1 class1 = new Class1();
sharedTestMethod(class1, "something");
}
@Test
public void test2() {
Class2 class2 = new Class2();
sharedTestMethod(class2, "else");
}
我们不要忘记缺点(由上面的链接引用):
注意缺点 访问方法的参数和返回类型需要提前知道,因此访问者模式不适用于这些访问的类可能发生变化的情况。每次添加新类型的元素时,都必须修改每个访问者派生类。此外,将访问者模式重构为尚未考虑到该模式的代码可能很困难。而且,当您添加访问者代码时,它可能看起来晦涩难懂。访客功能强大,但您应确保仅在必要时使用它。
推荐阅读
- c# - 从节点列表中获取子节点的值,XML Xpath C#
- javascript - 系列工具提示中的 Echart 图标
- c - 多次重用原始套接字或创建新套接字
- ssis - 错误 Odatasource 编辑器 System.Net.HttpWebresponse
- angular - Angular 静态注入器错误 - 没有 API 提供者
- php - codeigniter 不返回 json/ajax 响应
- ios - UITableView 逐个单元格更改图像和标题位置
- javascript - 将元素添加到传递的 jQuery 选择器
- sockets - 如何使用 Overbyte ICS 获取 500 错误的详细信息
- react-native - 如何在本机反应中清除抽屉导航器内的屏幕