# Installation

Use npm command in order to install BHrick-test module:

```bash
npm install [--save[-dev]] BHrick-test
```

# Usage

BHrick-test module is a simple unit-test library allowing:

  - BHrick env mocking
  - object and class mock creation
  - mocked method control (call counter, return value, asynchronous behaviour)
  - mocked property control (value)
  - control of Node "require" function

BHrick-test is working with mocha and have a direct dependency on it.

## Exemples

### Simple brick unit test

```js
'use strict';

/**
 * Libs.
 */
const Assert = require('assert');
const BHrickTest = require('bhrick-test');

/**
 * Brick definition.
 */
class Brick {
  run (env) {
    return env.valueGen
      .getValue()
      .then((value) => {
        return value + env.valueGen.staticValue - 1;
      });
  }
}

BHrickTest.startTest('Brick', (helpers) => {
  /**
   * Generating mocks.
   */
  helpers
    .createMock('VALUE_GEN')
    .addMethod('getValue')
    .addProperty('staticValue');
  /**
   * Mocking BHrick env.
   */
  helpers
    .addToEnv('VALUE_GEN', 'valueGen');
  /**
   * Test using mocha as usual.
   */
  describe('run', () => {
    it('Should return the good number', (done) => {
      let tested = new Brick();

      /**
       * Define mock behaviour for this test.
       */
      helpers
        .mock('VALUE_GEN')
        .method('getValue')
        .async()
        .shouldBeCalled(1)
        .willAlwaysReturn(10);
      helpers
        .mock('VALUE_GEN')
        .property('staticValue')
        .willBeEqualTo(15);

      tested
        .run(helpers.getEnv())
        .then((result) => {
          try {
            Assert.equal(24, result);
            done();
          } catch (e) {
            done(e);
          }
        })
        .catch((e) => {
          done(e);
        });
    });
  });
});
```

### Difference between Object and Class mocking

```js
'use strict';

/**
 * Libs.
 */
const Assert = require('assert');
const BHrickTest = require('bhrick-test');

/**
 * Code exemple.
 */
let someCodeUsingObject = function someCodeUsingObject (object) {
  return object.someMethod();
};
let someCodeUsingClass = function someCodeUsingClass (Class) {
  let object = new Class();

  return object.someMethod();
};

BHrickTest.startTest('Object and Class mocking', (helpers) => {
  /**
   * By default, the following mock will be an object.
   */
  helpers
    .createMock('OBJECT')
    .addMethod('someMethod');
  /**
   * Call prototype mock method to transform your mock into a class.
   */
  helpers
    .createMock('CLASS')
    .prototype()
    .addMethod('someMethod');
  /**
   * Test using mocha as usual.
   */
  describe('object', () => {
    it('Should use an object properly', () => {
      helpers
        .mock('OBJECT')
        .method('someMethod')
        .shouldBeCalled(1)
        .willReturn('ok'); // Can be chained to test multiple call

      /**
       * If u use a mock directly (outside of a bhrick env), do not forget to call compile() to instantiate your mock.
       */
      Assert.equal('ok', someCodeUsingObject(helpers.mock('OBJECT').compile()));
    });
  });
  describe('class', () => {
    it('Should use a class properly', () => {
      helpers
        .mock('CLASS')
        .method('someMethod')
        .shouldBeCalled(1)
        .willReturn('ok'); // Can be chained to test multiple call

      /**
       * If u use a mock directly (outside of a bhrick env), do not forget to call compile() to instantiate your mock.
       */
      Assert.equal('ok', someCodeUsingClass(helpers.mock('CLASS').compile()));
    });
  });
});
```

### Replace the Node "require" function to inject your mocks

Tested file, with the call to Node "require":

```js
'use strict';

/**
 * Libs.
 */
const MyInjection = require('my-injection');

class MyInjectionUser {
  doSomething () {
    let object = new MyInjection();

    return object.doSomething();
  }
}

module.exports = MyInjectionUser;
```

Tests file:

```js
'use strict';

/**
 * Libs.
 */
const Assert = require('assert');
const BHrickTest = require('bhrick-test');

BHrickTest.startTest('Replace the Node "require" function to inject your mocks', (helpers) => {
  helpers
    .createMock('MY_INJECTION')
    .prototype()
    .addMethod('doSomething');
  /**
   * Replace 'my-injection' module by our mock. Mock will be compiled on "require" call.
   */
  helpers.loader.addModule('my-injection', helpers.mock('MY_INJECTION'));
  /**
   * Require our file.
   */
  helpers.loader.enable();
  const MyInjectionUser = require('../src/injection.js');
  helpers.loader.disable();
  /**
   * Test using mocha as usual.
   */
  describe('Injection', () => {
    it('Should inject our mock via Node "require"', () => {
      let tested = new MyInjectionUser();

      helpers
        .mock('MY_INJECTION')
        .method('doSomething')
        .shouldBeCalled(1)
        .willAlwaysReturn(10);

      Assert.equal(10, tested.doSomething());
    });
  });
});
```

### Some tricks

Tested file:

```js
'use strict';

/**
 * Libs.
 */
const Net = require('net');

/**
 * The following code may have no sense !
 */
class NetUser {
  constructor () {
    this.socket = new Net.Socket(); // Create a Node Socket
  }

  connectMySocket () {
    this.socket.connect({
      'host': '127.0.0.1',
      'port': 4242
    });

    return this;
  }
}

module.exports = NetUser;
```

Tests file:

```js
'use strict';

/**
 * Libs.
 */
const BHrickTest = require('bhrick-test');

BHrickTest.startTest('Some tricks', (helpers) => {
  helpers
    .createMock('SOCKET')
    .prototype()
    .addMethod('connect');
  helpers
    .createMock('NET')
    .addProperty('Socket');
  /**
   * Replace 'net' module by our mock. Mock will be compiled on "require" call.
   */
  helpers.loader.addModule('net', helpers.mock('NET'));
  helpers.loader.enable();
  const NetUser = require('../src/net.js');
  helpers.loader.disable();
  /**
   * Test using mocha as usual.
   */
  describe('Net', () => {
    it('Should use the socket properly', () => {
      helpers
        .mock('NET')
        .property('Socket')
        .willBeEqualTo(helpers.mock('SOCKET').compile());

      let tested = new NetUser();

      helpers
        .mock('SOCKET')
        .method('connect')
        .shouldBeCalled(1);

      tested.connectMySocket();
    });
  });
});
```
