GithubHelp home page GithubHelp logo

gitter-badger / mockk Goto Github PK

View Code? Open in Web Editor NEW

This project forked from mockk/mockk

0.0 1.0 0.0 254 KB

Mocking framework for Kotlin

License: Apache License 2.0

Java 15.07% CSS 0.08% Kotlin 84.54% Shell 0.31%

mockk's Introduction

mockk

Nice features

  • removing finals (via Java Agent)
  • pure kotlin mocking DSL
  • partial arguments matchers
  • chained calls / deep stubs
  • matcher expressions
  • mocking coroutines
  • capturing lambdas
  • bunch of matchers
  • few verification modes

Installation

There is two installation steps.

First you need to add dependency to the library itself.

GradleMaven
testCompile "io.mockk:mockk:1.0.0"
    <dependency>
        <groupId>io.mockk</groupId>
        <artifactId>mockk</artifactId>
        <version>1.0.0</version>
        <scope>test</scope>
    </dependency>

Second you need to add class transformation agent. This agent is required to remove final modifier from running classes. There is few ways to add Java Agent/Class Loader. Only running as a Java Agent is an officially supported way. All others are existing for convenience and should be used at your own risk.

MethodInstruction
Java Agent gradle Add agent gradle plugin. Use following agent:
agent "io.mockk:mockk-agent:1.0.0"
Java Agent maven Add dependency to mockk-agent. Configure maven surefire plugin:
<argLine>-javaagent:${io.mockk:mockk-agent:jar}</argLine>
Java Agent JVM Add JVM parameter to launch agent:
-javaagent:libs/mockk-agent-1.0.0.jar
JUnit4 Add this dependency to your project:
testCompile "io.mockk:mockk-agent:1.0.0"
Use annotation for each test:
@RunWith(MockKJUnit4Runner::class)
If @RunWith is specified on superclass then it will be used to run after class loader is set. So you can specify next runner doing the real running job. Use @ChainedRunWith to override such delegated runner. If neither is specified default JUnit runner is used.
JUnit5 Just add this dependency to your project:
testCompile "io.mockk:mockk-agent:1.0.0"
JUnit5 test will be hooked via TestExecutionListener. Note: this implementation is totally a hack.

DSL

Simplest example:

  val car = mockk<Car>()

  every { car.drive(Direction.NORTH) } returns Outcome.OK

  car.drive(Direction.NORTH) // returns OK

  verify { car.drive(Direction.NORTH) }

Partial argument matching

You can skip parameters while specifying matchers. MockK runs your block few times, builds so called signature and auto-detects places where matchers appear:

  class MockedClass {
      fun sum(a: Int, b: Int) = a + b
  }

  val obj = mockk<MockedClass>()

  every { obj.sum(1, eq(2)) } returns 5

  obj.sum(1, 2) // returns 5

  verify { obj.sum(eq(1), 2) }

Chained calls

Mock can have child mocks. This allows to mock chains of calls:

  class MockedClass1 {
      fun op1(a: Int, b: Int) = a + b
  }

  class MockedClass2 {
      fun op2(c: Int, d: Int): MockedClass1 = ...
  }

  val obj = mockk<MockedClass2>()

  every { obj.op2(1, eq(2)).op1(3, any()) } returns 5

  obj.op2(1, 2) // returns child mock
  obj.op2(1, 2).op1(3, 22) // returns 5

  verify { obj.op2(any(), 2).op2(3, 22) }

Capturing

Simplest way of capturing is capturing to the CapturingSlot:

  class MockedClass {
      fun sum(a: Int, b: Int) = a + b
  }

  val obj = mockk<MockedClass>()
  val slot = slot<Int>()

  every { obj.sum(1, capture(slot)) } answers { 2 + slot.captured }

  obj.sum(1, 2) // returns 4

  verify { obj.sum(1, 2) }

Capturing lambda

You can capture lambdas with CapturingSlot<Any>, but for convenience there is captureLambda construct present:

  class MockedClass {
      fun sum(a: Int, b: () -> Int) = a + b()
  }

  val obj = mockk<MockedClass>()
  val slot = slot<Int>()

  every { obj.sum(1, captureLambda(Function0::class)) }
      answers { 2 + lambda.invoke() }

  obj.sum(1) { 2 } // returns 4

  verify { obj.sum(1, any()) }

Capturing to the list

If you need several captured values you can capture values to the MutableList. Method captured() is returning the last element of the list.

  class MockedClass {
      fun sum(a: Int, b: Int) = a + b
  }

  val obj = mockk<MockedClass>()
  val lst = mutableListOf<Int>()

  every { obj.sum(1, capture(lst)) } answers { 2 + lst.captured() }

  obj.sum(1, 2) // returns 4

  verify { obj.sum(1, 2) }

Verification with atLeast

Checking at least how much method was called:

  class MockedClass {
      fun sum(a: Int, b: Int) = a + b
  }

  val obj = mockk<MockedClass>()
  val lst = mutableListOf<Int>()

  every { obj.sum(any(), capture(lst)) }
      answers { 1 + firstArg() + lst.captured() }

  obj.sum(1, 2) // returns 4
  obj.sum(1, 3) // returns 5
  obj.sum(2, 2) // returns 5

  verify(atLeast=3) { obj.sum(any(), any()) }

Verification sequence

Checking the exact sequence of calls:

  class MockedClass {
      fun sum(a: Int, b: Int) = a + b
  }

  val obj = mockk<MockedClass>()
  val slot = slot<Int>()

  every { obj.sum(any(), capture(slot)) } answers { 1 + firstArg() + slot.captured }

  obj.sum(1, 2) // returns 4
  obj.sum(1, 3) // returns 5
  obj.sum(2, 2) // returns 5

  verifySequence {
      obj.sum(1, 2)
      obj.sum(1, 3)
      obj.sum(2, 2)
  }

Returning nothing

If the method is returning Unit(i.e. no return value) you still need to specify return value:

  class MockedClass {
      fun sum(a: Int, b: Int): Unit {
          println(a + b)
      }
  }

  val obj = mockk<MockedClass>()

  every { obj.sum(any(), 1) } answers { nothing }
  every { obj.sum(any(), 2) } returns null

  obj.sum(1, 1)
  obj.sum(1, 2)

  verify {
      obj.sum(1, 1)
      obj.sum(1, 2)
  }

DSL tables

Here is a few tables helping to master the DSL.

Matchers

Matcher Description
any() matches any argument
allAny() special matcher that uses any() instead of eq() for matchers that are provided as simple arguments
isNull() checks if values is null
isNull(inverse=true) checks if values is not null
ofType(type) checks if values belongs to the type
match { it.startsWith("string") } matches via arbitary lambda expression
eq(value) matches if value is equal to the provided via deepEquals method
refEq(value) matches if value is equal to the provided via reference comparation
cmpEq(value) matches if value is equal to the provided via compareTo method
less(value) matches if value is less to the provided via compareTo method
more(value) matches if value is more to the provided via compareTo method
less(value, andEquals=true) matches if value is less or equals to the provided via compareTo method
more(value, andEquals=true) matches if value is more or equals to the provided via compareTo method
and(left, right) combines two matchers via logical and
or(left, right) combines two matchers via logical or
not(matcher) negates the matcher
capture(mutableList) captures a value to a list
captureNullable(mutableList) captures a value to a list together with null values
captureLambda(lambdaClass) captures lambda expression(allowed one per call)

Validators

Validator Description
verify { mock.call() } Do unordered verification that call were performed
verify(inverse=true) { mock.call() } Do unordered verification that call were not performed
verify(atLeast=n) { mock.call() } Do unordered verification that call were performed at least n times
verify(atMost=n) { mock.call() } Do unordered verification that call were performed at most n times
verify(excatly=n) { mock.call() } Do unordered verification that call were performed at exactly n times
verifyOrder { mock.call1(); mock.call2() } Do verification that sequence of calls went one after another
verifySequence { mock.call1(); mock.call2() } Do verification that only the specified sequence of calls were executed for mentioned mocks

Answers

Answer Description
returns value specify that matched call returns one specified value
returnsMany list specify that matched call returns value from the list, returning each time next element
throws ex specify that matched call throws an exception
answers { code } specify that matched call answers with lambda in answer scope

Answer scope

Parameter Description
call a call object that consists of invocation and matcher
invocation contains information regarding actual method invoked
matcher contains information regarding matcher used to match invocation
self reference the object invocation made
method reference to the method invocation made
args reference to arguments of invocation
nArgs number of invocation argument
firstArg() first argument
secondArg() second argument
thirdArg() third argument
lastArg() last argument
caputred() the last element in the list for convenience when capturing to the list
lambda captured lambda
nothing null value for returning nothing as an answer

Getting Help

To ask questions please use stackoverflow or gitter.

To report bugs, please use the GitHub project.

mockk's People

Contributors

oleksiyp avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.