【问题标题】:The mock of my class isn't getting called我班级的模拟没有被调用
【发布时间】:2019-03-10 15:15:41
【问题描述】:

我有一个HelperMethod 课程。

class HelperMethods {
    def getUniqueID(): UUID = {
        UUID.randomUUID()
    }

    def bucketIDFromEmail(email:String): Int =  {

        val bucketID= email(0).toInt
        println("returning id "+bucketID+" for name "+email)
        bucketID
   }
}

还有一个object,它有一个HelperMethods 的实例

package object utilities{
    private val helper = new HelperMethods()
    def getUniqueID(): UUID = helper.getUniqueID()
    def bucketIDFromEmail(email:String): Int = helper.bucketIDFromEmail(email)  
}

我编写了一个规范来测试我的模拟是否正常工作。

class UserControllerUnitSpec extends PlaySpec {

val mockHelperMethods = mock(classOf[HelperMethods])

  when(mockHelperMethods.getUniqueID()).thenReturn(UUID.fromString("87ea52b7-0a70-438f-81ff-b69ab9e57210"))
  when(mockHelperMethods.bucketIDFromEmail(ArgumentMatchers.any[String])).thenReturn(1)

  "mocking helper class " should {
    "work" in {
      val bucketId = utilities.bucketIDFromEmail("t@t.com")
      println("user keys are " + userKeys)

      val id: UUID = utilities.getUniqueID()
      println("got id " + userKeys)

      bucketId mustBe 1
      id mustBe UUID.fromString("87ea52b7-0a70-438f-81ff-b69ab9e57210")

    }
  }
}

测试失败,原因为116 was not equal to 1。这对应于线 bucketId mustBe 1 在规范中。我可以看到打印returning id 116 for name t@t.com。我不应该看到它,因为我试图模拟这门课。我怀疑这可能是因为 utilities 对象是在规范中的声明 val mockHelperMethods = mock(classOf[HelperMethods]) 之前创建的。

问题 2- 有没有办法模拟 HelperMethods 并使 utilities 使用模拟类?

【问题讨论】:

    标签: scala mockito


    【解决方案1】:

    你嘲笑了HelperMethods,但没有嘲笑utilities

    问题 2- 有没有办法模拟 HelperMethods 并使实用程序使用模拟的类?

    无法模拟object

    如果需要,您必须提取 trait 中的行为。

    这是一个可行的解决方案:

    package utils
    
    // move the behavior to a trait:
    trait UtitilitiesTrait {
      private[utils] def helper = new HelperMethods()
    
      def getUniqueID(): UUID = helper.getUniqueID()
    
      def bucketIDFromEmail(email: String): Int = helper.bucketIDFromEmail(email)
    }
    
    // provide an object for real use
    object Utilities extends UtitilitiesTrait
    
    // override helper for test mock
    object TestUtilities extends UtitilitiesTrait {
      private[utils] override def helper = mock(classOf[HelperMethods])
    }
    

    这是你的测试:

    class UserControllerUnitSpec extends PlaySpec {
    
       val mockHelperMethods = mock(classOf[HelperMethods])
       object TestUtilities extends UtitilitiesTrait {
         private[utils] override def helper = mockHelperMethods
       }   
       when(mockHelperMethods.getUniqueID()).thenReturn(UUID.fromString("87ea52b7-0a70-438f-81ff-b69ab9e57210"))
          when(mockHelperMethods.bucketIDFromEmail(ArgumentMatchers.any[String])).thenReturn(1)
    
      "mocking helper class " should {
        "work" in {
          val bucketId = TestUtilities.bucketIDFromEmail("t@t.com")
          println("user keys are " + userKeys)
    
          val id: UUID = TestUtilities.getUniqueID()
          println("got id " + userKeys)
    
          bucketId mustBe 1
          id mustBe UUID.fromString("87ea52b7-0a70-438f-81ff-b69ab9e57210")
    
        }
      }
    }
    

    【讨论】:

    • 谢谢。如何让测试选择 TestUtilities 而不是 Utilities?
    • 我在答案中添加了测试 - 如果您需要更多解释,请告诉我
    • 谢谢。这说得通。虽然有一个限制,但这是因为我没有完全解释这个场景。就我而言,规范中有一个controller,实际上调用utilities.getUniqueID()(成像规范调用controller.handle messagehandlemessage调用实用程序.getUniqueID. I suppose I'll need to inject either Utilities`或TestUtilities,这取决于我是什么尝试做。
    【解决方案2】:

    实现内部使用的模拟对象的典型模式是注入它们,或者至少提供一种注入替代对象的方法。

    由于Utilities 是一个对象,因此您不能使用构造函数进行注入。您仍然可以引入 setter 方法。

    如果您不希望将 setter 用于单元测试以外的任何内容,请将其设为包私有,并且您还可以在名称前加上“qa”:

    private[utils] def qaSetHelperMethods(qaHelper: HelperMethods): Unit
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-10-15
      • 1970-01-01
      • 1970-01-01
      • 2017-11-17
      • 1970-01-01
      • 1970-01-01
      • 2016-03-31
      相关资源
      最近更新 更多