How can I use jasmine.js to test for console output?
Asked Answered
P

3

13

I'm working through the text: Professional JavaScript for Web Developers by Nicholas Zakas and I'm testing the examples with Jasmine.js.

I can currently test the output of a function by specifying a return a value, but I'm running into trouble when there are multiple pieces of data that I want to return.

The textbook uses the alert() method, but this is cumbersome and I don't know how to test for alerts. I was wondering if there was a way to test for console.log() output. For instance:

function_to_test = function(){
    var person = new Object();
    person.name = "Nicholas";
    person.age = 29;

    return(person.name);    //Nicholas
    return(person.age);     //29
});

I know I can have them return as one string, but for more complicated examples I'd like to be able to test the following:

function_to_test = function(){
    var person = new Object();
    person.name = "Nicholas";
    person.age = 29;

    console.log(person.name);    //Nicholas
    console.log(person.age);     //29
});

The Jasmine test looks something like:

it("should test for the function_to_test's console output", function(){
    expect(function_to_test()).toEqual("console_output_Im_testing_for");
});

Is there a simple way to do this that I'm just missing? I'm pretty new to coding so any guidance would be appreciated.

Piccolo answered 6/11, 2013 at 23:25 Comment(1)
Errr, no, return(person.name); return(person.age); is completely wrong. Only the first return statement will execute, the second will never be reached. The larger problem here is that you seem to be testing the internals of a function. You really have no business knowing what the function does internally, you should only be testing its output. Whatever you're actually returning from that function is what you should test.Fetation
D
27

There are a couple of things that are wrong with your code above. As pointed out, having multiple return statement will not work. Also, when defining a new object, it is preferable to use the object literal syntax over using new Object.

What you would normally do is something more like this:

var function_to_test = function () {
  var person = {
    name : "Nicholas",
    age : 29
  };

  return person;
};

Using the function above, there are a couple of ways you could test this. One it to mock out the console.log object using Jasmine Spies.

it("should test for the function_to_test's console output", function () {
    console.log = jasmine.createSpy("log");
    var person = function_to_test();
    expect(console.log).toHaveBeenCalledWith(person);
});

The other is to test the actual output of the function.

it("should return a person", function () {
    var person = function_to_test();
    expect(person).toEqual({ name : "Nicholas", age : 29 });
});
Denotative answered 12/11, 2013 at 21:17 Comment(5)
You cannot override the native console functions using a jasmine spy. They are unassignableKaunas
Of course, of course. For some reason I was expecting to have to enter another sub-variable to the console.log like console.log.print or something to test what was actually printed to the console. Semantics, right? Thanks and +1, C§Amylum
console.log = jasmine.createSpy('log') worked for me. I recommend saving the original function in a variable so it can be restored after the tests. I had to use beforeEach and afterEach to do this.Bailsman
@JordanPickwell : can you please let me know what did you use in your afterEach ??Thanatopsis
@Gagan: Sorry for the late reply. I have let originalLogFunc near the top of my test file. beforeEach: beforeEach(function () { originalLogFunc = console.log; console.log = jasmine.createSpy('log') }). afterEach is the reverse: afterEach(function () { console.log = originalLogFunc; originalLogFunc = undefined }).Bailsman
T
6

I know this is an old question (7+ years old) but I just came upon this answer today through Google search. From this answer, I changed it to the following and has worked for me.

spyOn(console, 'error');
const dto = new DTO();  // add to console.error if no parameter is given
expect(console.error).toHaveBeenCalled();
Taco answered 11/2, 2021 at 18:23 Comment(0)
L
0

Please try this,

function_to_test = function(){
  var person = new Object()
  person.name = "Nicholas"
  person.age = 29

  console.log(person.name)    //Nicholas
  console.log(person.age)     //29
});

describe('test',()=>{
  it("should test for the function_to_test's console output", ()=>{
    const logSpy = spyOn(console, 'log')
    function_to_test ()
    expect(logSpy.calls.count()).toBe(2) // "console.log" called twice
    expect(logSpy.calls.all()[0].args[0]).toBe("Nicholas") 
    expect(logSpy.calls.all()[1].args[0]).toBe(29)
  })
})

Hope it helps,

thanks

Literality answered 27/6 at 11:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.