Unit testing http get method in component - unit-testing

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.

Related

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

Ember Js testing a service with promises

How to test a method inside a service that returns a store in Ember Unit Test using qunit
export default Ember.Service.extend({
store: Ember.inject.service(),
setSomeProps() {
this.get('store').find('somemodel', id)
.then((someData) => {
this.set('someProp', someDate.get('name'));
});
}
});
The setSomeProps is a method inside my service, I am fairly new to ember and cannot get my head around ember unit test. Whats the best way to write a unit test for this function
You can mock the store service in your unit test of store-caller-service.
You should use wait function for asynchronous test behaviour which is described here.
Take a look at this twiddle example

Faking a module in angular 2 test

I have a function in angular 2 service which I would like to test.
service.ts
upload(){
let file = new Transfer();
file.upload(myfile).then( // my callback );
}
I would like to mock Transfer in my test using jasmine. I tried this in my
sevice.spec.ts
import { TransferMock as Transfer } from '../mocks/mocks' to mock it. But it is not working. This is how my test is instantiated .
describe('authentication service' , () => {
beforeEach(() => {
auth = new Service(<any>new HttpMock(), <any>new StorageMock())
});
it('initialize authentication',() => {
expect(auth).not.toEqual(null);
auth.upload('file'); //it fails here
});
})
edit
Transfer is not injected in the service. Only one function uses Transfer . So not injecting can reduce the initial loading time of the app i guess(would be happy to know other opinions) . So I would like to know if there is anyway to mock if its constructed this way ?
edit
Although I had accepted Martin's answer as it is the best practice, it has one issue which can happen when you use ionic-native plugins.If the plugin doesnt have browser support it can fail. In this case it happened when I inject it, with error FileTransfer is not defined . So I am back again, looking for suggestions.
In order to provide a mock for a class in a test, you need to inject the class in your implementation.
In your ngModule add Transfer to your providers. Then simply inject it into your service.
Then in your test you can use { provide: Transfer, useClass: TransferMock } in your TestBed providers.
Update
The primary purpose of Dependency Injection is to make code testable and to allow mocking - faking - stubbing of services.
Update
With Dependancy Injection you can configure a different set of providers for different environments.
For example, if you are running your application in the browser, and in a native mobile environment you can swap out your configuration.
In your module you could have something like this:
const TRANSFER_PROVIDER: any;
if (environment.browser) {
TRANSFER_PROVIDER = Transfer;
} else {
TRANSFER_PROVIDER = { provide: Transfer, useClass: NativeTransfer }
}
...
providers: [ TRANSFER_PROVIDER ]
NativeTransfer could be a simple stub that does nothing but prevent errors, or it could let the user know that this feature is not supported in their browser.

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

How do I get a resource from an Angular.js module for a jasmine test

I have a module that contains resources for a project, and the code looks like this:
editor_services.js
var editorServices = angular.module('editorServices', ['ngResource']);
editorServices.factory('Project', ['$resource', '$http',function($resource, $http){
//...etc
now I would like to write tests for a controller that expects a project resource as an argument. How can I get an instance of the project resource that is created by this factory out of the editorServices variable?
Here is a working example how one would test Resources (or http) in angular
http://plnkr.co/edit/kK5fDFIVpyZTInH1c6Vh?p=preview
The basic setup is:
load angular-mocks.js in your test. This replaces the $httpBackend with mock version. See: http://docs.angularjs.org/api/ngMock.$httpBackend
In your test call $httpBackend.expect() to create expectation to be mocked out.
When you want to simulate server response call $httpBackend.flush()
There is a caveat that normal .toEqual() from jasmine dose not work with $resource so you have to create custom matcher like so:
beforeEach(function() {
this.addMatchers({
// we need to use toEqualData because the Resource hase extra properties
// which make simple .toEqual not work.
toEqualData: function(expect) {
return angular.equals(expect, this.actual);
}
});
});