You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scala中如何Mock LocalDate.now()?测试func1的something方法

如何Mock Scala Object中的something2方法

因为Scala的object是单例实现,直接mock它的方法不像普通类那么容易,下面给你两种可行的方案:

方案一:重构代码(推荐)

最稳妥的方式是先重构代码,让依赖可注入,避免直接依赖单例的something2方法,测试起来更灵活:

方式1:将逻辑提取到特质中

把something2的逻辑抽到特质里,让func1依赖这个特质,测试时替换成mock实现:

trait DateProvider {
  def getDate(): LocalDate
}

object func1 extends DateProvider {
  def something(arg1: Int): String = {
    val date = getDate()
    // 原业务逻辑
    s"Processed $arg1 with date $date"
  }

  override def getDate(): LocalDate = LocalDate.now()
}

测试时,直接实现一个测试用的DateProvider:

class Func1Test extends AnyWordSpec {
  "something method" should {
    "use mocked date" in {
      val mockDate = LocalDate.of(2024, 1, 1)
      val testFunc1 = new DateProvider {
        override def getDate(): LocalDate = mockDate
      } with {
        def something(arg1: Int): String = {
          val date = getDate()
          s"Processed $arg1 with date $date"
        }
      }

      val result = testFunc1.something(123)
      assert(result == "Processed 123 with date 2024-01-01")
    }
  }
}

方式2:将something2作为参数传入

修改something方法,把something2作为可选参数,测试时传入mock的函数:

object func1 {
  def something(arg1: Int, dateFunc: () => LocalDate = something2): String = {
    val date = dateFunc()
    // 原业务逻辑
    s"Processed $arg1 with date $date"
  }

  def something2(): LocalDate = LocalDate.now()
}

测试时直接传mock的函数:

class Func1Test extends AnyWordSpec {
  "something method" should {
    "use mocked date" in {
      val mockDate = LocalDate.of(2024, 1, 1)
      val result = func1.something(123, () => mockDate)
      assert(result.contains("2024-01-01"))
    }
  }
}

方案二:使用PowerMock直接Mock单例(不推荐,仅用于无法重构的场景)

如果实在不能重构代码,可以用PowerMock配合Mockito来mock Scala单例的方法。需要先添加测试依赖,再编写测试:

1. 添加依赖(以sbt为例)

libraryDependencies ++= Seq(
  "org.scalatest" %% "scalatest" % "3.2.15" % Test,
  "org.powermock" % "powermock-module-junit4" % "2.0.9" % Test,
  "org.powermock" % "powermock-api-mockito2" % "2.0.9" % Test,
  "org.mockito" %% "mockito-scala" % "1.17.12" % Test
)

2. 编写测试代码

import org.junit.runner.RunWith
import org.powermock.core.classloader.annotations.PrepareForTest
import org.powermock.modules.junit4.PowerMockRunner
import org.powermock.api.mockito.PowerMockito
import org.scalatest.BeforeAndAfterEach
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec

@RunWith(classOf[PowerMockRunner])
@PrepareForTest(Array(classOf[func1]))
class Func1PowerMockTest extends AnyWordSpec with Matchers with BeforeAndAfterEach {

  override def beforeEach(): Unit = {
    PowerMockito.mockStatic(classOf[func1])
    // 保留something方法的原实现
    PowerMockito.when(func1.something(anyInt())).thenCallRealMethod()
  }

  "something method" should {
    "use mocked something2 result" in {
      val mockDate = LocalDate.of(2024, 1, 1)
      PowerMockito.when(func1.something2()).thenReturn(mockDate)

      val result = func1.something(123)
      result should include(mockDate.toString)
    }
  }
}

注意:PowerMock会修改类加载器,可能带来兼容性问题,所以优先推荐重构代码的方案。

内容的提问来源于stack exchange,提问作者Pawan Asipu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 07:45:35