首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >模拟java类中的scala对象方法调用

模拟java类中的scala对象方法调用
EN

Stack Overflow用户
提问于 2021-06-23 17:51:48
回答 2查看 46关注 0票数 0

我有一段java代码,其中我调用了一个scala对象的方法(属于一个依赖库)。为了编写单元测试,我想模拟scala对象的方法调用

Operations.scala

代码语言:javascript
复制
object Operations {

     def load(spark: SparkSession, path: String): Dataset[Row] = {

     }
}

Main.java

代码语言:javascript
复制
public class Main {
    public void callMethod() {
         Dataset<Row>  df = Operations.load(sparkSession, path);
    }
}

我想为callMethod()编写一个单元测试,从而模拟Operations.load scala调用。我没有找到一种方法来做这件事。

任何帮助都将不胜感激。

EN

回答 2

Stack Overflow用户

发布于 2021-06-23 19:09:53

如果您希望更改callMethod方法的签名,一种可能的解决方案是使用接口和依赖项注入。

创建一个为您提供Dataset[Row]的接口

代码语言:javascript
复制
trait ObtainDataSet {
  def obtain: DataSet[Row]
}

然后让你的callMethod有一个接受这个接口的参数:

代码语言:javascript
复制
public void callMethod(ObtainDataSet obtainDataSet) {
  Dataset<Row>  df = obtainDataSet.obtain;
}

然后在生产代码中使用Operations.load方法注入真正的实现:

代码语言:javascript
复制
class ObtainDataSetImpl(spark: SparkSession, path: String) extends ObtainDataSet {
  override def obtain: Dataset[Row] = Operations.load(sparkSession, path)
}

但是,您可以很容易地将该生产实现替换为测试中的特别实现。你甚至不需要使用模拟框架:

代码语言:javascript
复制
class MyMock extends ObtainDataSet {
  override def obtain: DataSet[Row] = ??? // something useful for tests.
}

但如果您愿意,通常会使用ScalaMock

票数 0
EN

Stack Overflow用户

发布于 2021-06-23 19:40:02

这通常是这样做的。我将用scala编写它,因为java的语法要冗长得多(坦率地说,我记不太清楚了),但它的概念是一样的。

代码语言:javascript
复制
   trait Operations { 
       def load(s: SparkSession, path: String): DataSet[Row]
   }
   object Operations extends Operations {
       def load(s: SparkSession, path: String) = ??? // implementation here
   }

   class Main(operations: Operations = Operations) {
       callMethod(): Unit = {
         val df = operations.load(sparkSession, path);
         ...
         // do stuff 
      }
   }

然后在测试中,您可以编写(这是使用Mockito/scalatest,但同样,对于您用于测试的任何库,想法也是相同的):

代码语言:javascript
复制
    val ops = mock[Operations]
    when(ops.load(any, any)).thenReturn(whatever)
    new Main(ops).callMethod(mock[SparkSession], "/foo/bar")

这种方法被称为“依赖注入”:您的Main类对Operations有一个“依赖”,现在是在运行时“注入”,而不是像在代码片段中那样被硬编码。这允许您为生产(实际的Operations对象)和测试(模拟)运行使用不同的依赖项实例。

此外,这是一个单独的主题,但我认为它仍然值得一提:您正在测试的方法的Unit (void)返回类型似乎不是最好的想法,并且可能会在以后的测试中给您带来更多问题(您如何确保该方法实际上产生了您所期望的副作用?)。

最好让此方法返回实际结果,并让调用者处理副作用。然后,您可以很容易地测试它是否产生了您期望的结果:

代码语言:javascript
复制
   new Main(ops).callMethod(mock[SparkSession], "/foo/bar") shouldBe "ExpectedFooResult"
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68097510

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档