agyan

Idiomatic mocking library for Crystal 💎

Agyan (अज्ञान, Ajñāna)

An idiomatic mocking library for Crystal 💎

Meaning of Agyan.

Installation

  1. Add the dependency to your shard.yml:

    development_dependencies:
      agyan:
        github: tkshnwesper/agyan
    
  2. Run shards install

Usage

How to use the library in a nutshell

  1. Create a mock class
  2. Instantiate the above class into an object
  3. Setup expectations and return values for methods on that object
  4. Pass that object into the code that you want to test

Import the library

require "agyan"

import Agyan

Create a class mock

mock_class can only be called at the root level or in modules, because it is a macro that creates a mock class, and classes have a limitation that they cannot be created inside methods.

class Garden
end

mock_class(Garden)  # Creates class called `MockGarden`

It also takes an optional name parameter

class Rocket
  def blast_off
  end
end

mock_class(Rocket, MockedRocket)  # Creates class called `MockedRocket`

# `blast_off` can now be mocked on an instance of `MockedRocket`

Define return values

class Vault
  def open : Bool
  end
end

mock_class(Vault)

describe Vault do
  it "opens vault" do
    mock = MockVault.new
    MockVault.on(mock, :open).with.then_return(true)
    mock.open.should be_truthy
  end
end

Return only when specific parameters are passed

class Vault
  def open(pin : Int32) : Bool
  end
end

mock_class(Vault)

describe Vault do
  it "opens vault" do
    mock = MockVault.new
    MockVault.on(mock, :open).with(123).then_return(true)
    mock.open(123).should be_truthy
  end
end

Assert expectations

Check whether your code is calling the mocked methods with the correct parameters.

class Vault
  def open(pin : Int32) : Bool
  end
end

mock_class(Vault)

describe Vault do
  it "opens vault" do
    mock = MockVault.new
    MockVault.on(mock, :open).with(123).then_return(true)
    MockVault.assert_expectations(mock) # raises exception as `open` is not called with `(123)`
  end
end

There is also support for overridden methods

class Vault
  def open(pin : Int32) : Bool
  end

  def open(pin : String) : Bool
  end
end

mock_class(Vault)

describe Vault do
  it "opens vault" do
    mock = MockVault.new
    MockVault.on(mock, :open).with(123).then_return(true)
    MockVault.on(mock, :open).with("Agyan").then_return(false)
    mock.open(123).should be_truthy
    mock.open("Agyan").should be_falsey
  end
end

Asserting on the initialize method

class ClassWithInitialize
  def initialize(value : Int32)
  end
end

mock_class(ClassWithInitialize)

describe ClassWithInitialize do
  it "mocks initialize methods" do
    MockClassWithInitialize.on(:initialize).with(10)
    mock = MockClassWithInitialize.new(10)
    MockClassWithInitialize.assert_expectations(mock)
  end
end

Development

Run tests using

crystal spec

Contributing

  1. Fork it (https://github.com/tkshnwesper/agyan/fork)
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

Contributors

Repository

agyan

Owner
Statistic
  • 1
  • 0
  • 0
  • 0
  • 0
  • over 3 years ago
  • April 5, 2021
License

BSD 3-Clause "New" or "Revised" License

Links
Synced at

Thu, 07 Nov 2024 05:20:15 GMT

Languages