I know, Browserify isn't really a DI framework, but is it possible to "inject", or somehow fake injecting, mock data into an application during unit testing?
For example, to test the function:
var MyModel = require('./models/My.js');
function doSomething() {
// do something with model.
}
with a mock My.js, like
describe('Do Something', function() {
beforeEach(function() {
// replace './models/My.js' with a Mock implementation.
});
it('with model', function() {
// ... test
});
})
what goes in the beforeEach function?
There are a few tools for mocking require calls in browserify.
https://github.com/thlorenz/proxyquireify
https://github.com/i-like-robots/rewireify
https://github.com/thlorenz/browserify-swap
https://github.com/Colingo/mock
https://github.com/mfncooper/mockery
I haven't personally used these. Also, mockery wasn't written with Browserify in mind so mockery might not even work. The others were written for Browserify though so they should work with little effort. :) Proxyquireify and Rewireify seem to be the only 2 active within the last year though.
Related
I'm having an exciting upgrade in a vue2 project using #vue/composition-api 0.6.7, trying to upgrade to 1.7.1.
Some tests are breaking and I'm noticing a pattern where the tests in question mount a component with the data parameter, as if they're reaching in and manipulating a ref
Example
// MyComponent.vue
<script>
export default defineComponent({
setup() {
const showModal = ref(false)
return {showModal}
}
})
</script>
Example test which was working before but now is broken.
it('should show the modal when the showModal ref is true', () => {
const wrapper = mount(MyComponent, {
data: {
showModal: true
}
});
expect(wrapper.find('#modal').exists()).toBe(true)
}
This makes sense to me that this broke in some ways because data is more of an options api thing and creating a ref is more of a composition-api thing-- probably more solidified as we went to 1.0 in the composition-api. That said, do you think that it should work?
When I rewrite the tests to NOT mount using the data prop and test it another way, the tests pass fine. I was expecting it to work as before and honestly not testing using the mount({data}), wrapper.setData(), or wrapper.vm seems like a better approach. I'm just looking for a confirmation or root cause why it worked before and not now.
Beyond this condensed code sample, I have tests using wrapper.setData({ serverResponse }) to simulate when a network call returns. This similarly breaks when I upgrade this composition-api package.
I was brought in on the "back-end" of a project and asked to help write tests for an app. I am very new to Ember and need just a little help getting started. We are trying to provide unit test for the routes, so we can have a bit more molecular scope over the app, instead of acceptance test. I have looked at some tutorials and went through every possible scenario that I could think of. I just need a bit of jumpstart.
Here is the part of the route.js for this route.
down stream of this parent route, we have another nested route that shows a list of contacts and when a user clicks on a show button it calls "model" and returns that variable "rec" for the template and the url
export default Route.extend(ScrollTo, {
flashMessages: service(),
model: function(params) {
let rec= this.store.peekRecord('contact', params.contact_id);
return rec;
},
actions: {
saveContact: function() {
let model = this.currentRouteModel();
model
.save()
.then(() => {
//this.refresh();
//this.setModelHash();
this.flashMessages
.success(`Saved Contact: ${model.get('title')}`);
//this.transitionTo('contacts');
});
}
Here is pre-generated code for the test. I really haven't made any modifications, because I really didn't know where to start.
This app doesn't have a back-end, it's design is to take in information and provide a iso file based on whatever standard the user wants.
I am sure I need to provide some mock data for the test and send that to the method, but again I am not sure what Qunit parts I use.
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
module('Unit | Route | contact/show', function(hooks) {
setupTest(hooks)
test('it exists', function(assert) {
var route = this.owner.lookup('route:contact/show');
assert.ok(route, 'contact.show route works');
});
});
I struggled with this as well when I first moved to frontend testing. With a few years experience I'm confident in saying you shouldn't unit test the route objects in this way. Instead the testing of an ember app should focus on two types of tests.
What ember calls integration tests (but are actually closer to UI unit tests)
Acceptance tests
Integration tests on components allow you to get into the smaller details and edge cases and they can be super valuable.
What I think you want in this case is actually an acceptance test.
If your testing experience is at all like mine it will feel like you're testing too many things at first, but these types of tests where the browser actually loads the entire application have the most value in hunting down bugs and are the most maintainable over time.
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;
});
});
I'm trying to test generator compose scenario. In my generator I call a sub-generator if a certain prompt returns true
if(this.bar){
this.composeWith('foo:bar', {});
}
I obviously test the bar sub-generator separately. However I would like to have an assert for this composeWith() to have been called. And I guess the problem is rather in my skills than yeoman testing docs but I have no idea how to do this. I understand that I need a spy and a stub. But the docs just list the functions and the tests for yeoman-generator itself are just mental (I tried reproducing their steps, but they mostly use dummies for everything and I only need to stub out the sub-generator).
Any help would be really appreciated. Thank you.
I admit the documentation is lacking on this point and we could improve it.
Here's a simple example of how you could use a spy to test your sub-generator is called:
var generators = require('yeoman-generator').generators;
var assert = require('yeoman-generator').assert;
before(function (done) {
this.spy = sinon.spy();
var Dummy = generators.Base.extend({
exec: this.spy
});
helpers.run('your/generator')
.withGenerators([
[Dummy, 'foo:bar']
])
.on('end', done);
});
// Then in your assertions
it('run the sub-generator', function () {
assert(this.spy.calledOnce);
});
I'm using this library at the moment to try to get Handlebars working on the server side of my meteor app (https://github.com/EventedMind/iron-router#using-a-layout-with-yields).
I've gotten it to work but I now want to fix my unit test. I'm a bit of a beginner at Jasmine so hopefully this question isn't too stupid. Tell me if I'm completely on the wrong track.
At the moment I'm trying to mock this line in a jasmine unit test.
Handlebars.templates['ResponseToSubscribers']({dateSent: new Date()})
I know how to mock methods, but I'm not sure how to mock array values.
I've tried doing this.
spyOn(Handlebars, 'templates').andReturn({"ResponseToSubscribers": (obj) -> "html"})
but it's giving me this error.
templates() method does not exist
How can I mock [] and get it return something?
A small correction to the way of adding a spy will solve the problem. Spy registration has to be done to the object and function/value on that object. Modifying the registration to spyOn(Handlebars.templates, 'ResponseToSubscribers') will solve your problem.
Sample Code:
describe("Test Array", function() {
it("checks the actual value", function() {
var t1 = Handlebars.templates['ResponseToSubscribers']('dummy');
expect(t1).toEqual(1);
});
it("checks handle bar value", function() {
spyOn(Handlebars.templates, 'ResponseToSubscribers').and.returnValue(2);
var t = Handlebars.templates['ResponseToSubscribers']('dummy');
expect(t).toEqual(2);
});
});