Preventing AJAX call with Jasmine and Sinon using Backbone - unit-testing

I'm just getting started testing my Backbone app with Sinon and Jasmine. I have a view that look something like (coffeescript):
initialize: ->
#collection.on 'reset', #render, this
render: ->
if #collection.fetched
# do stuff
else
#$el.append "<h3>Loading...</h3>"
#collection.fetch()
this
I want to test this with an unfetched collection, but I'm not sure how to fake an ajax call within my code (obviously can easily be done in the spec). I realize that I could just pass in a pre-fetched collection, but I'm curious -- is it possible with Sinon to override the fetch function to return a fake response?
Thank you for any help.

Under the hood, Backbone uses jQuery's $.ajax method, so you can stub that out. We use this to catch accidental calls in our Jasmine specs:
$.ajax = -> throw "ajaxShouldBeStubbedOutError: #{JSON.stringify arguments}"
And then you can stub over that if you want to fake an AJAX call and its response:
spyOn($,'ajax').andCallFake (options) =>
if options.url is "/correct"
options.success {"data":"yay"}

Related

How do I mock mailchimp_transactional in jest

I'm trying to figure out how to correctly mock the #mailchimp/mailchimp_transactional npm module in my tests.
I'm getting caught up in how it shows to import mailchimp from the documentation, with an immediate call to the constructor with the API key
const mailchimp = require('#mailchimp/mailchimp_transactional')(API_KEY);
According to the Jest documentation, I'd normally mock it with something like
jest.mock('#mailchimp/mailchimp_transactional');
But I'm not sure how to then create the instance with a fake API key? I keep getting an undefined result from trying to call the mocked version of mailchimp. Would I need to mock a constructor() function as well?
I think it should be something like this:
jest.mock(
'#mailchimp/mailchimp_transactional',
() => API_KEY => ({ object that mocks mailchimp })
);

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;
});
});

Unit testing http get method in component

I am new to testing and angular 5.
I have a component function which in turn calls the http get method and retuns json data.
I would like to test it.
this is my component function snippet
this.enablebutton=false;
this.users=[];
getUsers(){
this.http.get(url).subscribe(result=>{this.users=result
if(this.users.length>0){
this.enablebutton=true;
}
})
}
on tutorials I find they have a seperate service layer for calling the web services to fetch data like this and for which we have test cases,but I am not using any services currently.
this.userService.getUsers().subscribe(result=> this.users= result);
I wrote my test case as
beforeEach(() => {
fixture = TestBed.createComponent(AppComponent);
component = fixture.componentInstance;
// spyOn(component, "getUsers").and.callThrough();
component.getUsers();
fixture.detectChanges();
});
I dont know how to set the values for result from http.get call manually and test the conditions for this.enablebutton which relies on the result from the http call.
Thank you.

How to mock only the authorize() method in Form Request on Laravel 5.1?

We are implementing resource ownership and/or input validations through the use of FormRequest. Our controller tests are functional test so we don't mock Request but use the $this->call($method, $url, $params, ...).
The issue is that FormRequest is a subclass of Request. Is there a way to mock only the authorize() method but keeping the rest of the Request object non-mocked?
If so, how to? I already tried partial mocking with Mockery and it either didn't work or I did it wrong.
$this->mock(\Namespace\Http\Requests\CustomRequest::class . '[authorize]')
->shouldReceive('authorize')
-> .......
Use phpunit mocking system instead of Mockery.
$request = $this->getMock(\Namespace\http\Requests\CustomRequest::class, ['authorize']);
$request->expects($this->once())->method('authorize')->willReturn(true);
hope it helps;

load json file for jasmine test with angular.js

I have mock data in an external json file that I want to have available for Jasmine unit tests in Angular.js. Unfortunately I am not approved to run node.js in my dev environment, so the usual karma examples don't apply to me.
I have tried:
beforeEach(inject(function ($injector, $http) {
console.log('this gets called');
$http.get('/mockData/surveySetup.json').success(function (data) {
console.log('this never gets called');
}).error(function () {
console.log('this never gets called');
});
}));
The console.log outside of the $http.get gets called, but the ones inside $http.get never fire, and I don't see a call to the json file in chrome's network tab.
What can I do to load this file to use in my tests? At the end of the day I just need to have access to the data in the .json file so I can refer to it in my unit tests.
Thanks in advance.
I found that I needed to convert my .json file to an Angular service (actually an Angular constant worked for my purposes). Then my external file was easy to grab in my tests, like so:
var setupData = $injector.get('SetupData');
$httpBackend.whenGET('/surveySetup').respond(setupData);
$httpBackend.flush();
Not sure what exactly are going to achieve but usually you can configure this by using $httpBackend which can be configured to mock the actual requests from any of your code (you may also need to setup with your URL syntax in this case but anyway this the common case for the unit tests. In this case you don't need to read the JSON file you can just provide the JS object inside of the $httpBackend configuration for that URL and when this URL is to be invoked $httpBackend will return the specified object. Look at: $httpBackend