mocking dataservice with bard js

2.7k Views Asked by At

I'm writing an angular controller, which has a depenedency on a dataservice (data service goes to http server), and I would like to mock its behavior.

I'm mocking with a library called bard js, and it has an api to mock services called bard.mockService.

In the beforeEach statement I'm doing:

beforeEach(function() {
    bard.appModule('app.process.creation');
    bard.inject('$controller', '$rootScope', '$q', 'processCreationDataservice');

    bard.mockService(processCreationDataservice, {
        createProcess: $q.when({}),
        _default: $q.when([])
    });

    controller = $controller('ProcessCreationController');
    $rootScope.$apply();
});

then my test:

it('should call create process data service to create process', function() {
    controller.create();
    expect(processCreationDataservice.createProcess).to.have.been.calledOnce;
});

As you can see in the test I want to assert that dataservice.createProcess is being called once.

The controller is not calling the method processCreationDataservice.createProcess, and still the test is passing.

(function() {
angular
    .module('app.process.creation')
    .controller('ProcessCreationController', ProcessCreationController);

ProcessCreationController.$inject = ['processCreationDataservice'];

function ProcessCreationController(processCreationDataservice) {
    var vm = this;

    vm.process = {
        name: '',
        bankId: ''
    };

    vm.create = function() {

    };
}})();

I would like to know why this test is passing, and what should I do to assert that the method is being called once.

I followed these instructions: https://github.com/wardbell/bardjs#mockService

2

There are 2 best solutions below

2
On BEST ANSWER

I believe that you neglected to load the sinon-chai script. You can quickly find out by pasting the following in your specs.html just below where you load sinon.js

<script src="https://rawgithub.com/domenic/sinon-chai/master/lib/sinon-chai.js"></script>

I typically pull down sinon-chai via npm

npm install sinon-chai --save-dev

and then my script becomes ...

<script src="/node_modules/sinon-chai/lib/sinon-chai.js"></script>

I'll bet your test fails, exactly as you would expect.

The omission of sinon-chai leads to a very subtle false positive. Follow me as as I explain:

Let's look at the assertion/expectation just before you say "calledOnce":

expect(processCreationDataservice.createProcess).to.have.been; // Assertion

It returns a chai Assertion. But that Assertion object lacks all of the sinon assertion methods such as calledOnce. The sinon-chai library extends chai with the sinon assertion methods.

So when you tack calledOnce to the end, you get:

expect(processCreationDataservice.createProcess).to.have.been.calledOnce; // undefined

Yup, the statement returns undefined ... which is an inert statement of no consequence to mocha. It's not an error. It's just a no-op. So the expect does nothing and mocha thinks the test passed.

You might as well have done this (it passes too):

expect(processCreationDataservice.foo /*undefined*/).to.have.been.calledOnce; // undefined

You don't have to use "sinon-chai". It's a convenience. But if you leave it out, you'll have to write the expectation this way:

  // without "sinon-chai"
  expect(dataservice.createThing.calledOnce).to.be.true;

I created a plunker for you (and others) to explore these dynamics.

1
On

This isn't really an answer I don't think, just a question. Why would you bring in a 3rd party http mock service, when angular has $httpBackend built in? If it was a conscious decision, what made you go for it?