How can I get jasmine to mock values of arrays? - unit-testing

I'm using this library at the moment to try to get Handlebars working on the server side of my meteor app (https://github.com/EventedMind/iron-router#using-a-layout-with-yields).
I've gotten it to work but I now want to fix my unit test. I'm a bit of a beginner at Jasmine so hopefully this question isn't too stupid. Tell me if I'm completely on the wrong track.
At the moment I'm trying to mock this line in a jasmine unit test.
Handlebars.templates['ResponseToSubscribers']({dateSent: new Date()})
I know how to mock methods, but I'm not sure how to mock array values.
I've tried doing this.
spyOn(Handlebars, 'templates').andReturn({"ResponseToSubscribers": (obj) -> "html"})
but it's giving me this error.
templates() method does not exist
How can I mock [] and get it return something?

A small correction to the way of adding a spy will solve the problem. Spy registration has to be done to the object and function/value on that object. Modifying the registration to spyOn(Handlebars.templates, 'ResponseToSubscribers') will solve your problem.
Sample Code:
describe("Test Array", function() {
it("checks the actual value", function() {
var t1 = Handlebars.templates['ResponseToSubscribers']('dummy');
expect(t1).toEqual(1);
});
it("checks handle bar value", function() {
spyOn(Handlebars.templates, 'ResponseToSubscribers').and.returnValue(2);
var t = Handlebars.templates['ResponseToSubscribers']('dummy');
expect(t).toEqual(2);
});
});

Related

Do my tests need to be rewritten when mounting a setup() based Vue2.6 component with data param? Upgrading #vue/composition-api from 0.6.7 to 1.7.1

I'm having an exciting upgrade in a vue2 project using #vue/composition-api 0.6.7, trying to upgrade to 1.7.1.
Some tests are breaking and I'm noticing a pattern where the tests in question mount a component with the data parameter, as if they're reaching in and manipulating a ref
Example
// MyComponent.vue
<script>
export default defineComponent({
setup() {
const showModal = ref(false)
return {showModal}
}
})
</script>
Example test which was working before but now is broken.
it('should show the modal when the showModal ref is true', () => {
const wrapper = mount(MyComponent, {
data: {
showModal: true
}
});
expect(wrapper.find('#modal').exists()).toBe(true)
}
This makes sense to me that this broke in some ways because data is more of an options api thing and creating a ref is more of a composition-api thing-- probably more solidified as we went to 1.0 in the composition-api. That said, do you think that it should work?
When I rewrite the tests to NOT mount using the data prop and test it another way, the tests pass fine. I was expecting it to work as before and honestly not testing using the mount({data}), wrapper.setData(), or wrapper.vm seems like a better approach. I'm just looking for a confirmation or root cause why it worked before and not now.
Beyond this condensed code sample, I have tests using wrapper.setData({ serverResponse }) to simulate when a network call returns. This similarly breaks when I upgrade this composition-api package.

Sort is not a function; spyOn not mocking

So I have a function with a sort that I am trying to unit test with Jasmine.
loadData() {
this.Service.getAll().subscribe(res => {
res.sort((x) => {
return x.Name, x.Id
});
this.stuff = res;
});
}
From what I have found, because the sort is an array.Prototype, I need to add a spyon the method. I have tried both of the following, but they don't handle it:
spyOn(Array.prototype,'sort').and.callThrough();
spyOn(Array.prototype,'sort');
I'm new to Jasmine, So I assume I am just missing something obvious. How do I handle this?
Thanks
It's a bad idea to spy on a prototype, you should spy on an instance instead. Take a look at this post. Actually, you are trying to test the method implementation, but you should test the class API instead. When you use a class, you don't think about its implementation, usually you even don't know how the class is implemented, it's just a black box. You should test the class the same way, otherwise it will be hard to maintain such tests, you'll have to update tests each time the implementation is changed. The loadData() method changes the object state somehow, just check that the state is changed correctly.

Checking middleware is called from http call

How would one test that a piece of custom middleware is actually called from a standard HTTP event?
ie. The middleware is called from:
MyController.js
router.get('/some/endpoint', [myMiddleware()], (req, res, next) => {
// Code to do whatever here
});
The middleware itself can be defined as:
MyMiddleware.js
module.exports = () => {
// Middleware code in here
}
My quest is to check that the middleware is called once from my unit test, but I cannot find documentation around this.
MyTest.test.js
it('Should return whatever from GET call', () => {
return request(app).get('/some/endpoint')
.expect(200)
.expect(res => {res.body.should.deep.equal(bodyValue)});
// How would I place code in here to check that MyMiddleware is called?
// ie. sinon.assert.calledOnce(MyMiddleware)
});
I have thought about using Sinon's spy, but I can't think of how to hook into the middleware... My attempt was this:
const mwSpy = sinon.spy(require('path to middleware file'));
sinon.assert(calledOnce(mwSpy));
The usual way of going about this is splitting this into two tests, an integration test and a unit test.
Will the middleware I specified in the router.get call end up being called when someone hits this endpoint?
Does my middleware do the right thing?
The first part is basically testing that the Express API is doing what the documentation says. That's not what unit tests are for (this was tagged unit-testing), but since you are already using HTTP requests to test the endpoint, I guess that's not what you are after anyway: you are basically creating verification tests for your system.
You could still test the Express routing without HTTP, though, as I detail in the answer to this question, concerning how to test the router programmatically (faster tests, no http), but less just stick to what you have.
So the basic question is: "My quest is to check that the middleware is called once from my unit test". You don't seem to concern yourself with whether the middleware is doing the right thing or not, just that it's called, which calls for the question on whether we should test the middleware or the layer using the middleware.
In both cases, you need to find a way of injecting a test spy. Either you write a small utility method that will inject that spy: function setMiddleware(module){ middleware = module; } or you use some tooling like proxyquire. See this tutorial on Sinon's homepage for background.
I would just do this (in the test code):
it('Should return whatever from GET call', () => {
var middlewareFake = sinon.fake();
// I am assuming it's the actual app object you are referencing below in the request(app) line
var app = proxyquire('../app/index.js', { './my-middleware': middlewareFake });
//
return request(app).get('/some/endpoint')
.expect(200)
.expect(res => {
res.body.should.deep.equal(bodyValue)
expect(middlewareFake).was.called;
});
});

Testing yeoman's composeWith

I'm trying to test generator compose scenario. In my generator I call a sub-generator if a certain prompt returns true
if(this.bar){
this.composeWith('foo:bar', {});
}
I obviously test the bar sub-generator separately. However I would like to have an assert for this composeWith() to have been called. And I guess the problem is rather in my skills than yeoman testing docs but I have no idea how to do this. I understand that I need a spy and a stub. But the docs just list the functions and the tests for yeoman-generator itself are just mental (I tried reproducing their steps, but they mostly use dummies for everything and I only need to stub out the sub-generator).
Any help would be really appreciated. Thank you.
I admit the documentation is lacking on this point and we could improve it.
Here's a simple example of how you could use a spy to test your sub-generator is called:
var generators = require('yeoman-generator').generators;
var assert = require('yeoman-generator').assert;
before(function (done) {
this.spy = sinon.spy();
var Dummy = generators.Base.extend({
exec: this.spy
});
helpers.run('your/generator')
.withGenerators([
[Dummy, 'foo:bar']
])
.on('end', done);
});
// Then in your assertions
it('run the sub-generator', function () {
assert(this.spy.calledOnce);
});

Injecting mocks into Browserify for testing

I know, Browserify isn't really a DI framework, but is it possible to "inject", or somehow fake injecting, mock data into an application during unit testing?
For example, to test the function:
var MyModel = require('./models/My.js');
function doSomething() {
// do something with model.
}
with a mock My.js, like
describe('Do Something', function() {
beforeEach(function() {
// replace './models/My.js' with a Mock implementation.
});
it('with model', function() {
// ... test
});
})
what goes in the beforeEach function?
There are a few tools for mocking require calls in browserify.
https://github.com/thlorenz/proxyquireify
https://github.com/i-like-robots/rewireify
https://github.com/thlorenz/browserify-swap
https://github.com/Colingo/mock
https://github.com/mfncooper/mockery
I haven't personally used these. Also, mockery wasn't written with Browserify in mind so mockery might not even work. The others were written for Browserify though so they should work with little effort. :) Proxyquireify and Rewireify seem to be the only 2 active within the last year though.