Assertions
Learn how to create and use assertions using the
expect()
function.
Overview
When testing your application, a test run consists of several different test cases, typically run in quick succession. Each test is meant to either return successfully or throw an error. Sometimes a failing test ‘naturally’ throws an error (from elsewhere in your code), but more often tests include assertions to validate certain values during the test run. An assertion compares a particular value based on an expected condition, and throws an error if the condition isn’t met.
The Desk test library provides a fluent API for creating assertions, including a wide range of assertion methods for different types of values. Assertions throw errors that are caught by the test (scope) runner, which then marks the test as failed with a detailed error message that includes the assertion and actual value(s).
Creating an assertion
The expect() function creates an assertion object for a particular value. However, the assertion itself doesn’t actually validate anything yet. The returned object is an instance of Assertion, which contains different methods to compare the encapsulated value based on a particular condition — for example, the .toBe()
method which checks for strict equality with another specified value.
- function expect(value, name?)Creates a new Assertion object, ready to evaluate the given value.
- class AssertionRepresents a value ready to be asserted.
// assert that a variable matches a specific value
expect(myResult).toBe(123);
expect(myString).toMatchRegExp(/foo/);
You can also negate the assertion by adding .not
in front of the assertion method. This turns the Assertion object into a new NegatedAssertion object.
- class NegatedAssertionRepresents a value ready to be asserted, using inverse logic.
// These are the same:
expect(2).toBeGreaterThan(1);
expect(2).not.toBeLessThanOrEqualTo(1);
Asserting equality
The following assertion methods can be used to validate that a value is (strictly) equal to a given value.
- toBe(value?)Asserts that the value is strictly equal to given value (using the
===
operator). - toBeUndefined()Evaluates toBe(undefined).
- toBeNull()Evaluates toBe(null).
- toBeOneOf(…values)Asserts that the value is strictly equal to one of given values.
- toEqual(value)Asserts that the value is loosely equal to given value (using the
==
operator). - toEqualOneOf(…values)Asserts that the value is loosely equal to one of given values.
The following method can be used to assert the type of a value (i.e. the result of typeof
).
- toBeTypeOf(typeStr)Asserts that the value is of given type.
Numeric assertions
In addition to equality assertions, the following assertion methods can be used to validate numeric values.
- toBeLessThan(value)Asserts that the value is less than given value.
- toBeLessThanOrEqualTo(value)Asserts that the value is less than or equal to given value.
- toBeGreaterThan(value)Asserts that the value is greater than given value.
- toBeGreaterThanOrEqualTo(value)Asserts that the value is greater than or equal to given value.
- toBeNaN()Asserts that the value is
NaN
.
Boolean assertions
The following assertion methods can be used to loosely check for ‘truthy’ and ‘falsy’ values. The asserted value is converted to a boolean value first, and then checked against true
or false
.
- toBeTruthy()Evaluates asBoolean().toBe(true).
- toBeFalsy()Evaluates asBoolean().toBe(false).
Note: It’s good practice to use the
.toBe()
method for strict equality checks when a value is expected to betrue
orfalse
— rather than.toBeFalsy()
which also succeeds for e.gundefined
.
String assertions
For assertions on string values, in addition to equality assertions (i.e. .toBe("string value")
), the following method can be used for pattern matching.
- toMatchRegExp(re)Asserts that the value is a string that matches given regular expression.
Object and array assertions
The following assertion methods can be used with objects.
- toBeInstanceOf(C)Asserts that the value is an instance of given class (using the
instanceof
operator). - toBeArray(match?)Asserts that the value is an array, optionally with given length or elements.
- toHaveProperty(propertyName)Asserts that the value is an object that includes a property with given name (using the
in
operator). - toHaveMethod(methodName)Asserts that the value is an object that includes a function property with given name.
Function and method call assertions
The following assertion methods can be used to call a function or method and check for errors.
- toThrowError(…args)Runs a function and asserts that it throws an error when called with given arguments.
- toThrowErrorAsync(…args)Runs a function and asserts that it throws an error or results in a promise that’s rejected.
These methods fail if the function or method doesn’t throw an error. They can be combined with .not
to check for the absence of an error.
If you’re not sure whether a function or method throws an error, but also don’t want to fail if an error was thrown, you can use the TestCase.tryRun() and TestCase.tryRunAsync() methods.
Conversion
The following assertion methods return another assertion, encapsulating a value that’s converted from the original asserted value to a particular type.
- asBoolean()Returns a new assertion for the boolean representation of the current value.
- asString()Returns a new assertion for the string representation of the current value.
- asNumber()Returns a new assertion for the number representation of the current value.
- asArray()Returns a new assertion for the return value of
Array.from(...)
on the current value. - asJSONString(replacer?, space?)Returns a new assertion for the JSON representation of the current value.
Chaining assertions
Several Assertion methods return a new assertion, which can be used for further validation by ‘chaining’ Assertion methods.
Property values
You can use the result of expect(value).toHaveProperty(name)
to validate the (value of the) property with given name.
// check that obj.foo is "bar":
let obj = { foo: "bar" };
expect(obj).toHaveProperty("foo").toBe("bar");
Note that expect(value).not.toHaveProperty(name)
never returns anything, since the given property doesn’t exist.
Similarly, expect(value).toHaveMethod(name)
returns an assertion for the method — this time as a bound function. That means it can be used directly with toThrowError()
and .not.toThrowError()
.
// check that num.toFixed(2) doesn't throw an error:
let num = 123;
expect(num).toHaveMethod("toFixed").not.toThrowError(2);
Return values and errors
The result of .not.toThrowError()
is an assertion for the function/method’s return value, allowing us to continue stringing assertion methods even further.
// ...as above, and check the return value:
let num = 123;
expect(num).toHaveMethod("toFixed").not.toThrowError(2).toBe("123.00");
Conversely, the result of .toThrowError()
for functions and methods that are supposed to throw an error is an assertion for the error that was caught, allowing us to check the error message, for example.
function doThrow() {
throw Error("Gotcha!");
}
expect(doThrow)
.toThrowError()
.toHaveProperty("message")
.toMatchRegExp(/Gotcha/);
// or convert error to a string:
expect(doThrow)
.toThrowError()
.asString()
.toMatchRegExp(/Gotcha/);