Reputation: 48
I have a function like this
$scope.openMail=function(mail){
DocumentTypes.getDocument(function(response){
$scope.documentTypes=response.result;
$log.log("documentTypes",$scope.documentTypes);
})
}
Spec for above fun is
it("should test open mail", function(){
scope.documentTypes=[{"type":"pdf"},{"type":"xml"}];
spyOn(documentTypes,"getDocument").and.callFake(function(){
return scope.documentTypes;
});
var mail='back';
scope.openMail(mail);
expect(scope.documentTypes).toEqual({"type":"pdf"},{"type":"xml"});
})
so the code is not covering for function(response){}
How can i cover this code in my code coverage? Thanks.
Upvotes: 4
Views: 682
Reputation: 3778
You have several problems with your test:
spyOn(documentTypes,"getDocument")
instead of spyOn(DocumentTypes,"getDocument")
scope.documentTypes
to the expected result of the test, i.e. the test passes no matter what the code does (unless you get an exception)mail
parameterHere's how I would test it:
describe('$scope.openMail', function() {
beforeEach(function() {
spyOn(DocumentTypes, 'getDocument');
});
it('uses DocumentTypes.getDocument service to get the document types', function() {
$scope.openMail('test_mail');
expect(DocumentTypes.getDocument).toHaveBeenCalledWith(jasmine.any(Function));
});
describe('provides a callback function that', function() {
beforeEach(function() {
DocumentTypes.getDocument.and.callFake(function (callback) {
callback('test_document_types');
});
});
it('stores the document types on the scope', function() {
$scope.openMail('test_mail');
expect($scope.documentTypes).toEqual('test_document_types');
});
// Note: This is optional, depending on whether you test logging or not
it('logs the document types', function() {
spyOn($log, 'log');
$scope.openMail('test_mail');
expect($log.log).toHaveBeenCalledWith('documentTypes', 'test_document_types');
});
});
});
Upvotes: 2
Reputation: 350
Assuming you are injecting DocumentTypes into your controller or whatever you have that openMail function in, you can mock it when performing tests. One way of doing that could be to use the $provide service.
This mock could look like this if using karma-chai-spies:
stubs = {
DocumentTypes: {
getDocument: chai.spy(function(callback)
{
callback({
result: [
"type"
]
});
})
}
};
Then provide it using $provide in your unit tests:
beforeEach(function()
{
module(function($provide)
{
$provide.value("DocumentTypes", stubs.DocumentTypes);
});
});
The test itself could then look something like this using karma-mocha and karma-chai:
it("should test open mail", function()
{
var controller = $controller('myController', {
$scope: stubs.$scope
});
stubs.$scope.openMail("mail");
expect(stubs.$scope.documentTypes).to.deep.equal([
"type"
]);
expect(stubs.DocumentTypes.getDocument).to.have.been.called.once();
});
Upvotes: 0
Reputation: 7265
I could be totally wrong here, but if that call to DocumentTypes.getDocument(...) is an async call you may need to trigger a digest cycle by calling scope.apply()
just after you call scope.openMail(mail)
Upvotes: 0