我对ScalaMock和嘲笑都是新手。我试图测试一个方法,它调用另一个(mocked)类中的方法,然后在返回的对象上调用方法。
详细资料:
所以我使用ScalaTest,这个测试涉及到五个类...
我正在测试的子指令
class SubInstruction(label: String, val result: Int, val op1: Int, val op2: Int) extends Instruction(label, "sub") {
override def execute(m: Machine) {
val value1 = m.regs(op1)
val value2 = m.regs(op2)
m.regs(result) = value1 - value2
}
}
object SubInstruction {
def apply(label: String, result: Int, op1: Int, op2: Int) =
new SubInstruction(label, result, op1, op2)
}
在测试中必须被嘲笑的机器
case class Machine(labels: Labels, prog: Vector[Instruction]) {
private final val NUMBEROFREGISTERS = 32
val regs: Registers = new Registers(NUMBEROFREGISTERS)
override def toString(): String = {
prog.foldLeft("")(_ + _)
}
def execute(start: Int) =
start.until(prog.length).foreach(x => prog(x) execute this)
}
object Machine extends App {
if (args.length == 0) {
println("Machine: args should be sml code file to execute")
} else {
println("SML interpreter - Scala version")
val m = Translator(args(0)).readAndTranslate(new Machine(Labels(), Vector()))
println("Here is the program; it has " + m.prog.size + " instructions.")
println(m)
println("Beginning program execution.")
m.execute(0)
println("Ending program execution.")
println("Values of registers at program termination:")
println(m.regs + ".")
}
}
构造机器对象所需的寄存器
case class Registers(size: Int) {
val registers: Array[Int] = new Array(size)
override def toString(): String =
registers.mkString(" ")
def update(k: Int, v: Int) = registers(k) = v
def apply(k: Int) = registers(k)
}
我创建为原始机器类的MockableMachine没有空构造函数,因此(据我所知)无法模拟
class MockableMachine extends Machine(Labels(), Vector()){
}
最后是我的测试类SubInstructionTest,它编译但抛出下面的异常。
class SubInstructionTest extends FlatSpec with MockFactory with Matchers {
val label1 = "f0"
val result1 = 25
val op1_1 = 24
val op2_1 = 20
val sub1 = SubInstruction(label1, result1, op1_1, op2_1)
"A SubInstruction" should "retrieve the operands from the correct registers in the given machine " +
"when execute(m: Machine) is called, and perform the operation saving the " +
"result in the correct register." in {
val mockMachine = mock[MockableMachine]
inSequence {
(mockMachine.regs.apply _).expects(op1_1).returning(50)
(mockMachine.regs.apply _).expects(op2_1).returning(16)
(mockMachine.regs.update _).expects(result1, 34)
}
sub1.execute(mockMachine)
}
}
抛出:
JAVAlang.NoSuchMethodException:寄存器。模拟$apply$0()
-
几个小时以来,我一直在寻找一种简单的方法来嘲笑这门课,但一无所获。目前,我已经确定了下面详细描述的变通方法,但我的印象是,嘲笑将为测试我的SubInstrucal类提供一个不那么复杂的解决方案。
解决办法:
删除MockableMachine类并创建一个CustomMachine类,该类扩展机器并用构造时提供的MockedRegister替换寄存器值。
class CustomMachine (mockedRegister: Registers) extends Machine(Labels(), Vector()) {
override
val regs: Registers = mockedRegister
}
作为原始类创建的MockableRegisters类没有空构造函数,因此(据我所知)无法模拟
class MockableRegisters extends Registers(32) {
}
和用稍微不同的方式编写的SubInstructionTest类
class SubInstructionTest extends FlatSpec with MockFactory with Matchers {
val label1 = "f0"
val result1 = 25
val op1_1 = 24
val op2_1 = 20
val sub1 = SubInstruction(label1, result1, op1_1, op2_1)
"A SubInstruction" should "retrieve the operands from the correct registers in the given machine " +
"when execute(m: Machine) is called, and perform the operation saving the " +
"result in the correct register." in {
val mockRegisters = mock[MockableRegisters]
val machine = new CustomMachine(mockRegisters)
inSequence {
(mockRegisters.apply _).expects(op1_1).returning(50)
(mockRegisters.apply _).expects(op2_1).returning(16)
(mockRegisters.update _).expects(result1, 34)
}
sub1.execute(machine)
}
}
如前所述,这对我来说就像是一个解决办法,难道没有更简单的方法来做到这一点(也许类似于我最初的尝试)?
我刚刚包含了问这个问题的基本代码,但是你可以在我的GitHub账户上找到完整的代码。
我认为Scalamock不支持隐式模拟嵌套对象。您必须模拟第一次调用返回的对象,这就是您的工作示例所做的。
FWIW,Mockito支持这一点。搜索RETURNS_DEEP_STUBS
。
问题内容: 我有四个让我们说A,B,C,D的类,每个类都从另一个调用方法。 现在我已经模拟了类A,并且想模拟使用嘲笑的方法 并希望在递归方法调用上获取“ foo” 应该回来 我试过了 when(a.getB()。getC()。getD())。thenReturn(“ foo”); 但是得到了nullPointerException 然后我尝试 doReturn(“ foo”)。when(a.get
我有4个类让说A,B,C,D,每一个调用的方法从另一个。 现在我已经模拟了类A,并想使用mockito模拟一个方法 但得到nullPointerException 然后我试着 doReturn(“foo”).When(A.getb().getc().getd()); 但我不能一次就做到吗?如有任何帮助,我们将不胜感激。
对于Mockito和其他测试框架,通常有方法在测试类中模拟方法的功能。我似乎无法让ScalaMock接受同样的方式。 在测试课上,我是: 我知道,如果你嘲笑/剔除类,然后在真实实例上调用相同的功能,这是行不通的。但是有一些变通方法,可以使用模拟调用等。 如果这是错误的方法,测试在同一个测试类中使用其他方法的方法的最佳方法是什么?我认为解耦方法是最好的实践。 谢谢
我试图模拟一个有嵌套类的类。那个嵌套类有一个构造函数参数。当我试图使用mockito而不是mockito测试时,实际的方法正在执行。 我在外部类上做了@injectmock,在内部类上做了@Mock。 我像往常一样尝试使用@Mock调用类,但是实际的方法eth1()正在被访问。 需要模拟内部ClassB方法,而不是访问真实方法。 作为mockito的初学者,我试图澄清这一点。但在访问void方法等
我试图测试一个类,它具有两个函数:和。加载,调用,然后执行一些操作并返回新的。为举例起见: 使用如何编写测试代码? 我试过: 我希望测试成功通过,并且得到(我知道scalamock用mock替换了所有现有函数,但这不是预期的行为) 编辑:我在mockito中找到了这个引用这个概念的答案,但我不确定scalamock是否支持这种嘲讽,以及为什么要反对这种嘲讽。
当我尝试模拟的任何其他方法时,模拟会起作用,但不能使用方法。 这是ScalaMock bug还是我做错了什么?