Scala:模拟和蛋糕模式 [英] Scala: Mocking and the Cake Pattern

查看:50
本文介绍了Scala:模拟和蛋糕模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试采用Cake Pattern,但在适应这种编程风格方面遇到困难,尤其是在涉及单元测试的地方.

I've been trying to adopt the Cake Pattern but I'm having difficulties adapting to this programming styles, especially where unit tests are concerned.

让我们假设我具有以下业务对象:

Lets assume that I have the following business objects:

trait Vet {
  def vaccinate(pet: Pet)
}

trait PetStore { this: Vet =>
  def sell(pet: Pet) {
    vaccinate(pet)
    // do some other stuff
  }
}

现在,我想在模拟Vet的功能时测试PetStore.如果使用组合,则将创建一个模拟[Vet]并将其传递给PetStore构造函数,然后像在Java世界中一样对模拟进行编程.但是,我找不到关于人们如何使用蛋糕模式进行此操作的任何参考.

Now, I'd like to test PetStore while mocking out the functions from Vet. If I was using composition, I was creating a mock[Vet] and passing it to the PetStore constructor, then programming the mock like we do in the Java world. However, I can't find any reference to how people do this with the cake pattern.

一个可能的解决方案是根据预期的用法在每个测试用例上实现vaccinate(),但是这不允许我验证是否正确调用了模拟程序,不允许我使用匹配器,等等.

One possible solution would be to implement vaccinate() on each test case according to the expected usage, but this then doesn't allow me to verify that the mocks were called properly, doesn't allow me to use matchers, etc.

那么-人们如何将Cake Pattern与模拟对象一起使用?

So - how are people using Cake Pattern with mock objects?

推荐答案

阅读此博客文章后,我开始使用蛋糕模式:

I started using the cake pattern after I read this blog post: https://github.com/precog/staticsite/blob/master/contents/blog/Existential-Types-FTW/index.md The approach is different from most Cake Pattern posts in that existential-types are used instead of self-types.

我使用这种模式已经有几个月了,而且看起来很不错,因为我可以在需要时指定一个模拟.它确实具有更多的依赖注入感觉,但是它具有将代码包含在特征中的所有好处.

I have been using this pattern for a few months and it seems to work out well as I can specify a mock when I want to. It does have more a dependency injection feel to it, but it has all the benefits you get of having your code in traits.

我使用存在类型的问题的混蛋版本是这样的:

My bastardized version of your problem using existential-types would be something like this:

case class Pet(val name: String)
trait ConfigComponent {
  type Config
  def config: Config
}

trait Vet {
  def vaccinate(pet: Pet) = {println ("Vaccinate:" + pet)}
}

trait PetStoreConfig {
  val vet: Vet
}
trait PetStore extends ConfigComponent {

    type Config <: PetStoreConfig

    def sell(pet: Pet) {
      config.vet.vaccinate(pet)
      // do some other stuff
    }
}

您可以将它们全部整合到您的应用中

You can put it all together in your app

class MyApp extends PetStore with PetStoreConfig {

  type Config = MyApp
  def config = this  

  val vet = new Vet{}
  sell(new Pet("Fido"))

}

scala> new MyApp
Vaccinate:Pet(Fido)
res0: MyApp = MyApp@668dd96c

您可以通过创建VetLike的实例并创建一个VetLike的模拟来单独测试组件,并在PetStore测试中使用它.

And you can test the components individually by creating an instance of VetLike and also creating a mock of VetLike an using it your PetStore test.

//Test VetLike Behavior
scala> val vet = new Vet{}
scala> vet.vaccinate(new Pet("Fido"))
Vaccinate:Pet(Fido)


//Test Petstore Behavior

class VetMock extends Vet {
   override def vaccinate(pet: Pet) = println("MOCKED")
}

class PetStoreTest extends PetStore with PetStoreConfig {
   type Config = PetStoreTest
   def config = this

   val vet = new VetMock
   val fido = new Pet("Fido")
   sell(fido)
}

scala> new PetStoreTest
MOCKED

这篇关于Scala:模拟和蛋糕模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆