Jasmine: Testing a function that uses a browser object - unit-testing

I am trying to test this function with Jasmine:
myFunc: function () {
var name = document.getElementById("bob");
display.innerHTML = name;
return 100;
}
The test fails with ReferenceError: document is not defined. I understand that I'm not running the test in a browser so document isn't defined. But how come mocking it out isn't working? Is there a way to write this test with standalone Jasmine only?
How would one generally go about testing these kinds of functions (JavaScript mixed with DOM)? I'd prefer not to use another library/framework.
// Mock, stub dom object.
var document;
beforeEach(function () {
document = jasmine.createSpyObj('document', ['getElementById', 'createElement']);
});
describe("myFunc", function () {
it("return 100", function () {
console.log(document); // My mock document object successfully logs.
expect(myFunc()).toEqual(100); // but document isn't defined in here.
});
});

Related

How to throw an exception upon first invocation and a regular return value on the second?

My code makes network calls. Sometimes these fail and I've implemented some retry logic. Now I wish to test this with a unit test. I'm using Mockito for this. I'm having trouble mocking this particular method call, this is my test code:
var mock = MockHttpClient();
var answers = <Future<String>>[
Future.error(Exception('boom')),
Future.value('some return value'),
];
when(mock.getStuff()).thenAnswer((_) => answers.removeAt(0));
var client = Client(inner: mock);
var result = client.someCall(); // This method call uses the `inner` object to make the `getStuff` network call.
expect(result, 'some return value');
Running this code throws an exception. And I get that because of the first returned Future! Mockito has the appropriate method call named thenThrow but I can't figure out how to combine the two.
I've figured it out. The trick is not to use a Mock but a Fake.
That looks like this:
class FakeHttpClient extends Fake implements HttpClient {
final List<Future<List<String>>> answers = [
Future.error(Exception('boom')),
Future.value('some return value'),
];
#override
Future<String> getStuff() {
return answers.removeAt(0);
}
}
Then use an instance of FakeHttpClient as an argument to the original example's Client:
var fake = FakeHttpClient();
var client = Client(inner: fake);
var result = client.someCall(); // This method call uses the `inner` object to make the `getStuff` network call.
expect(result, 'some return value');

use jest mock functions to test code that calls another server

Roughly, my JavaScript function that I want to unit-test looks like this:
const request = require('request-promise-native');
async function callServer() {
// Prepare parameters
// Call `request` with parameters
// Parse response JSON and return
}
Is there any way to unit-test this function without making an actual call to the real server? Can I use a jest mock function to somehow override request()? To do that, will I need to modify every function to take the request function as a parameter or there is another way?
You can mock imported module via jest.mock. https://jestjs.io/docs/en/api#requirerequiremockmodulename
describe('main description', () => {
it('description of test case', () => {
jest.mock('request-promise-native', () => {
return {}; // Return what the request-promise-native supposed to return
});
const result = callServer();
expect(result).toBe({});
});
});

Unit tests with FluentValidation. How to mock ValidationResult

I'm using TDD approach with xUnit 2, NSubstitute, AutoFixture, FluentAssertions for my unit tests.
I want test my service method which using FluentValidation.
Simple example:
Validator:
RuleSet("Nulls", () =>
{
RuleFor(viewModel => viewModel).NotNull();
});
My service(under test):
if(Validate(viewModel, "Nulls"))
//....
private bool Validate(AddMerchantViewModel viewModel, string option)
{
var result = _merchantValidator.Validate(viewModel, ruleSet: options);
return result.IsValid;
}
And my unit test:
I don't know how to mock the merchantValidator.Validate result.
[Theory, AutoNSubstituteData]
public void Add_ViewModelAsNull_ShouldThrowArgumentNullException(
AbstractValidator<AddMerchantViewModel> merchValidator,
MerchantsService service)
{
// Arrange
//here I don't know how to mock result of Validate. It is always null.
merchantValidator.Validate(Arg.Any<AddMerchantViewModel>(), ruleSet: Arg.Any<string>()).Return(new ValidationResult());
// Act
Action action = () => service.Add(null);
// Assert
action.ShouldThrow<ArgumentNullException>();
}
By default AutoFixture creates a new instance of a type every time it's requested. In this particular case the AbstractValidator<AddMerchantViewModel> type is instantiated twice - as the merchValidator parameter and as a dependency of the MerchantsService class.
As a result the configured validator is not used by the service. In order to fix that you should decorate the merchValidator parameter with the [Frozen] attribute so that the same instance of the AbstractValidator<AddMerchantViewModel> type is always returned by AF:
[Theory, AutoNSubstituteData]
public void Add_ViewModelAsNull_ShouldThrowArgumentNullException(
[Frozen]AbstractValidator<AddMerchantViewModel> merchValidator,
MerchantsService service)
// ...
More info abot the [Frozen] attribute can be found here.

Spy on a local function Angular Service

I have an Angular Service using a local function and doing the following work:
function myService($http,$q){
var myService = {};
var _localService = function (Table) {
return Table.something;
}
var _getSomething = function () {
return _localService('someTable');
}
var _getSomethingElse = function () {
return _localService('someTable2');
}
myService.getSomething = _getSomething ;
myService.getSomethingElse = _getSomethingElse ;
return myService ; }
Now i want to test my service with jasmine and i want to test if localService have been called.
Something like this:
spyOn(myService,"_localService");
myService.getSomething();
expect(myService._localService).toHaveBeenCalled();
How can i do that, please help.
You have to expose _localService in your service or else the spy can't find it.
Because in fact you made it private by returning myService without a _localService function.
So you can keep it private, or make it public, if it's public, it will work as is.
If you want to keep it private, then,
you shouldn't test private function, instead test what you expect as a result to the call of the public function. It will allow to refactor inner implementation and still have test to check that your code works.

Attempted to wrap sendRequest which is already wrapped

I'm writing unit tests using Jasmine for my Backbone cache and am trying to mock up a function response using Sinon.js. For different tests, I expect different things to happen so I am creating a mock before each test and deleting it after, then filling in the expects behavior within the test itself. However, I'm getting an error and the tests are failing.
Here's my spec with just the relevant tests (other tests aren't using mock):
describe("mysite.core.Cache.XFooInfo", function() {
var fnMock;
beforeEach(function() {
fnMock = sinon.mock(fn);
});
afterEach(function() {
delete fnMock;
});
it("should make a request after function fooCreated called", function() {
fnMock.expects("sendRequest").once().withExactArgs("ModuleFoo", "getFoo", ["1000"]);
events.trigger("fooCreated", [{Args:[test.data.XFooInfo]}]);
fnMock.verify();
});
});
describe("mysite.core.Cache.XFooBarInfo", function() {
var fnMock;
beforeEach(function() {
fnMock = sinon.mock(fn);
});
afterEach(function() {
delete fnMock;
});
it("should make a request after function booUpdated called", function() {
var booCopy = $.extend(true, {}, test.data.XBooInfo);
booCopy[0].Args[0].FooID = "12345";
fnMock.expects("sendRequest").once().withExactArgs("ModuleFoo", "getFoo", ["12345"]);
events.trigger("booUpdated", booCopy);
fnMock.verify();
});
});
The first test works fine and passes. The second test, however, gives me this error:
TypeError: Attempted to wrap sendRequest which is already wrapped
at Object.wrapMethod (https://localhost:8443/mysite/web/tests/libs/sinon-1.7.1.js:528:23)
at Object.expects (https://localhost:8443/mysite/web/tests/libs/sinon-1.7.1.js:2092:27)
at null.<anonymous> (https://localhost:8443/mysite/web/shasta-cList-tests/spec/CacheSpec.js:909:15)
at jasmine.Block.execute (https://localhost:8443/mysite/web/tests/libs/jasmine-1.2.0.rc3/jasmine.js:1024:15)
at jasmine.Queue.next_ (https://localhost:8443/mysite/web/tests/libs/jasmine-1.2.0.rc3/jasmine.js:2025:31)
at jasmine.Queue.start (https://localhost:8443/mysite/web/tests/libs/jasmine-1.2.0.rc3/jasmine.js:1978:8)
at jasmine.Spec.execute (https://localhost:8443/mysite/web/tests/libs/jasmine-1.2.0.rc3/jasmine.js:2305:14)
at jasmine.Queue.next_ (https://localhost:8443/mysite/web/tests/libs/jasmine-1.2.0.rc3/jasmine.js:2025:31)
at jasmine.Queue.start (https://localhost:8443/mysite/web/tests/libs/jasmine-1.2.0.rc3/jasmine.js:1978:8)
at jasmine.Suite.execute (https://localhost:8443/mysite/web/tests/libs/jasmine-1.2.0.rc3/jasmine.js:2450:14)
I can't find anything in the Sinon.js docs to tell me what I'm doing wrong. I know verify also does a restore on all the functions it mocks and I thought that it was enough to allow me to write a new expects behavior for the same function, but apparently I was wrong.
What is the right way to do this?
Ok, so after spending 2 hours on this problem last Friday with no luck, I figured it out twenty min after posting this question. Adding var fn.sendRequest = function(module, fnName, args) {}; to the beforeEach function fixed all the failing tests.
this one works too, less to type:
var fn.sendRequest = function () { };