how can I write unit test to my meteor methods? - unit-testing

I found it a little complicated, and more complicated if I wrote my meteor methods in /lib folder, that I want is to test from server test folder my methods (unit test), but stub this.userId and also debugging or showing logs in server side does not help too much.
I was having too much problems with it, I'm using mochajs with velocity, does anyone would help me please? is someone know how can I write the units to meteor methods?

Mocha doesn't support unit tests, only Jasmine does currently. This is an example of how you would write a unit test in Jasmine for the server and use userId.
it("should return premium content to logged in users", function () {
// SETUP
var thisContext = {
userId : true
};
var expectedCursor = 'chapter_cursor1';
var _query = true, _modifiers = true;
Chapters.find = function(query, modifiers) {
_query = query;
_modifiers = modifiers;
return expectedCursor;
};
// EXECUTE
var actualCursor = Meteor.publishFunctions['chapters'].apply(thisContext);
// VERIFY
expect(actualCursor).toBe(expectedCursor);
expect(_query).toBe(undefined);
expect(_modifiers).toBe(undefined);
});
Taken from here: https://github.com/xolvio/Letterpress/blob/master/tests/jasmine/server/unit/chaptersSpec.js#L3

Related

Navigation Unit Testing in MvvmCross

Trying to unit test the navigation in one of my command calls into a private method. Just trying to test if the navigation request has been made as a result of this command execution.
There's the old documentation;
https://www.mvvmcross.com/documentation/fundamentals/testing
This documentation does not factor in new async based calls as far as I found; For example IMvxMainThreadAsyncDispatcher
Either we need to implement two ExecuteOnMainThreadAsync methods or inherit from MvxMainThreadAsyncDispatcher in MockDispatcher.
Also need to add IMvxMainThreadAsyncDispatcher in IoC registration.
var mockDispatcher = new MockDispatcher();
...
...
Ioc.RegisterSingleton<IMvxMainThreadAsyncDispatcher>(MockDispatcher);
So almost all tests work except navigation call requests. Below method inside MockDispatcher never gets called so I can't check request counts;
public async Task<bool> ShowViewModel(MvxViewModelRequest request)
{
Requests.Add(request);
return true;
}
Anybody has a working code that would mock and gets this Request called or in some other form? IMvxMainThreadDispatcher is being set as absolute, and navigation calls are not done with ShowViewModel<>() anymore in MVVMCross, it's done by calling navigationService.Navigate();
Well, I have found the solution to my question... The ShowViewModel is called when navigation service is properly mocked. I have found a piece of code on GitHub from MvvmCross's own repo on how they do tests for navigation. My next challenge would be to mock the destination viewModel but that's separate and below code doesn't cover that. Previously I had a very basic IMvxNavigationService mock.
var mockLocator = new Mock<IMvxViewModelLocator>();
mockLocator.Setup(
m => m.Load(It.IsAny<Type>(), It.IsAny<IMvxBundle>(), It.IsAny<IMvxBundle>(), It.IsAny<IMvxNavigateEventArgs>())).Returns(() => new FakeViewModel());
mockLocator.Setup(
m => m.Reload(It.IsAny<IMvxViewModel>(), It.IsAny<IMvxBundle>(), It.IsAny<IMvxBundle>(), It.IsAny<IMvxNavigateEventArgs>())).Returns(() => new FakeViewModel());
var mockCollection = new Mock<IMvxViewModelLocatorCollection>();
mockCollection.Setup(m => m.FindViewModelLocator(It.IsAny<MvxViewModelRequest>()))
.Returns(() => mockLocator.Object);
Ioc.RegisterSingleton(mockLocator.Object);
var loader = new MvxViewModelLoader(mockCollection.Object);
_navigationService = new MvxNavigationService(null, loader)
{
ViewDispatcher = MockDispatcher,
};
_navigationService.LoadRoutes(new[] { typeof(YourViewModelTestClass).Assembly });
Ioc.RegisterSingleton<IMvxNavigationService>(_navigationService);

Moq out parameters

I'm fairly new to using Moq and Nunit for unit testing and I'm having issues with one scenario. What I want is for my mock to have an out parameters which my system under test will then use to decide what action to take.
My system under test is an MVC API controller and in particular I'm trying to test the POST method. I want to return an error message for the object when validation fails.
Here is the method code for the controller:
public IHttpActionResult Post(Candidate candidate)
{
try
{
if(candidate==null)
return BadRequest();
IEnumerable<string> errors;
_candidateManager.InsertCandidate(candidate, out errors);
if (errors!=null && errors.Any())
return BadRequest(CreateErrorMessage("Invalid candidate: ", errors));
return CreatedAtRoute("DefaultApi", new {id = candidate.CandidateId}, candidate);
}
catch (Exception)
{
return InternalServerError();
}
}
This is my Unit Test Code:
[Test]
[Category("CandidateManagerController Unit Tests")]
public void Should_Return_Bad_Request_When_Creating_Invalid_Candidate()
{
IEnumerable<string> errors = new List<string>() {"error1", "error2"};
var mockManager = new Mock<ICandidateManager>();
mockManager.Setup(x => x.InsertCandidate(new Candidate(), out errors)).Callback(()=>GetErrors(errors));
var sut = new CandidateManagerController(mockManager.Object);
var actionResult = sut.Post(new Candidate());
Assert.IsInstanceOf<BadRequestResult>(actionResult);
}
What I expect is that when _candidateManager.InsertCandidate() is run then the errors variable is populated. However what is happening is that when you step through the controller code errors is null after _candidateManager.InsertCandidate() method is run.
If anyone has any ideas what I'm doing wrong or if what I want to do is not possible using Moq then please let me know.
Thanks
What you want to do is possible. If you look at the Quickstart docs at https://github.com/Moq/moq4/wiki/Quickstart, there is a section where it shows how you do setups for methods using out params. I have made two corrections to your code and it works.
You have to use the same candidate instance for both the mock setup and when you exercise the sut. Otherwise, Moq thinks that the two objects are different and your test setup becomes useless.
You don't have to use Callback in order to set the errors returned by the mocked CandidateManager.
Below is your test method with my changes.
[Test]
[Category("CandidateManagerController Unit Tests")]
public void Should_Return_Bad_Request_When_Creating_Invalid_Candidate()
{
IEnumerable<string> errors = new List<string>() {"error1", "error2"};
//instance to be used for both setup and test later
var candidate = new Candidate();
var mockManager = new Mock<ICandidateManager>();
//removed Callback
mockManager.Setup(x => x.InsertCandidate(candidate, out errors));
var sut = new CandidateManagerController(mockManager.Object);
var actionResult = sut.Post(candidate);
Assert.IsInstanceOf<BadRequestResult>(actionResult);
}
You have to make sure that when you call your SUT that you use the same instance passed to the out argument otherwise the call will fail.
In your example, the method under test passes a null instance into the mocked method thus negating the setup of the test.
If however you are not able to supply the same instances for the out then it doesn't look like you will be able to get a mock to pass successfully. Take a look a the Quick Start for Moq to get an understanding of it capabilities.

how to unit-test setInterval in karma angularjs

app.directive('shuffleBlocks', function($timeout){
return {
link: function(sco,ele,att){
if (itemCnt <= 1) return;
/*Trigger function*/
function triggerEvent(){
...
}
ele.bind('click', triggerEvent);
setInterval(triggerEvent, 5000);
}
}
})
here I wrote the test
var elem = '<div shuffle-blocks><div>';
elem = mockCompile(elem)(rootScope.$new());
setInterval(function(){
expect(......).toBe(....)
});
Obviously this is not the right method,
does anyone know how to test $timeout and setInterval in karma?
UPDATE: The proper method of mocking setInterval in an angular 1.2+ application is to use angular's $interval service. Using the $interval service provides a number of benefits, but the one of most use in this situation is the $interval.flush() method. When writing tests, $interval exposes a .flush() method which allows you to mock the JS clock.
app.directive('shuffleBlocks', function($timeout, $interval){
return {
link: function(sco,ele,att){
if (itemCnt <= 1) return;
/*Trigger function*/
function triggerEvent(){ ... }
ele.bind('click', triggerEvent);
$interval(triggerEvent, 5000);
}
}
});
and then in your unit test:
var elem = '<div shuffle-blocks><div>';
elem = mockCompile(elem)(rootScope.$new());
$interval.flush(5000); // flush accepts the # of ms to be flushed
expect(......).toBe(....);
Hope that's helpful to anyone who looks up this answer in the future. I'll leave my previous answer for those still using 1.1X.
Previous Answer: According the jasmine docs, you should be able to just use the jasmine.Clock.useMock() function to mock the typical javascript clock and manually work your way through the interval. Since angular is just wrapping the native setTimeout function, I'm quite positive it should allow this to work, though I haven't tested it to be sure.
The jasmine docs for version 1.3 are here. Here's the code example that demonstrates how it works.
beforeEach(function() {
timerCallback = jasmine.createSpy('timerCallback');
jasmine.Clock.useMock();
});
it("causes a timeout to be called synchronously", function() {
setTimeout(function() {
timerCallback();
}, 100);
expect(timerCallback).not.toHaveBeenCalled();
jasmine.Clock.tick(101);
expect(timerCallback).toHaveBeenCalled();
});
The only issue I see is that your triggerEvent() function is local to your link function, so I don't know how you'll be able to get to it to mock it. But hopefully that points you in the right direction. If not, sorry, I tried.
UPDATE: The syntax for mocking the clock has changed in Jasmine 2.0. If you are using 2.0, please see the updated docs here.

using mocha testing with cloud9, execute mocha tests from node.js

I was wondering if there is a way to execute mocha tests programmatically from node.js so that I can integrate unit tests with Cloud 9. The cloud 9 IDE has a nice feature where whenever a javascript files is saved, it looks for a file with the same name, ending with either "_test" or "Test" and runs it automatically using node.js. For example it has this code snippet in a file demo_test.js which automatically runs.
if (typeof module !== "undefined" && module === require.main) {
require("asyncjs").test.testcase(module.exports).exec()
}
Is there something like this I could use to run a mocha test? Something like a mocha(this).run()?
The essentials to programmatically run mocha:
Require mocha:
var Mocha = require('./'); //The root mocha path (wherever you git cloned
//or if you used npm in node_modules/mocha)
Instatiate call the constructor:
var mocha = new Mocha();
Add test files:
mocha.addFile('test/exampleTest'); // direct mocha to exampleTest.js
Run it!:
mocha.run();
Add chained functions to programmatically deal with passed and failed tests. In this case add a call back to print the results:
var Mocha = require('./'); //The root mocha path
var mocha = new Mocha();
var passed = [];
var failed = [];
mocha.addFile('test/exampleTest'); // direct mocha to exampleTest.js
mocha.run(function(){
console.log(passed.length + ' Tests Passed');
passed.forEach(function(testName){
console.log('Passed:', testName);
});
console.log("\n"+failed.length + ' Tests Failed');
failed.forEach(function(testName){
console.log('Failed:', testName);
});
}).on('fail', function(test){
failed.push(test.title);
}).on('pass', function(test){
passed.push(test.title);
});
Your mileage may vary, but I concocted the following one-liner a while back and it has served me pretty well:
if (!module.parent)(new(require("mocha"))()).ui("exports").reporter("spec").addFile(__filename).run(process.exit);
Additionally, if you want it to be output in asyncjs format that Cloud9 is expecting, you'll need to provide a special reporter. Here's a really simple example of what a simple reporter would look like:
if (!module.parent){
(new(require("mocha"))()).ui("exports").reporter(function(r){
var i = 1, n = r.grepTotal(r.suite);
r.on("fail", function(t){ console.log("\x1b[31m[%d/%d] %s FAIL\x1b[0m", i++, n, t.fullTitle()); });
r.on("pass", function(t){ console.log("\x1b[32m[%d/%d] %s OK\x1b[0m", i++, n, t.fullTitle()); });
r.on("pending", function(t){ console.log("\x1b[33m[%d/%d] %s SKIP\x1b[0m", i++, n, t.fullTitle()); });
}).addFile(__filename).run(process.exit);
}

First Unit Tests! ASP.NET MVC with Repositories causing errors

I am very new to Unit Testing, so I am starting on my first set of tests today. I am using the Library JustMock from Telerik. Though any unit testing information is good. I am having a bit of trouble with an interface service that passes through my method. Below is my MembershipController.Register(model) method...
[CaptchaValidator]
[HttpPost]
public ActionResult Register(Models.Membership.Registration model)
{
// just for good mesure, truncate any spaces that are given
System.Text.RegularExpressions.Regex.Replace(model.Email, #"\s", "");
if (ModelState.IsValid)
{
// Attempt to register the User and return any applicable status that has to do
// with the result.
var createStatus = membershipService.RegisterMember(model.Email, model.Password);
// if the member is able to be created successfully, log them in now and begin the
// authentication portion of the registration, otherwise, display the registration
// errors and return to the view.
if (createStatus == Membership.MemberCreateStatus.Success)
{
formsAuthentication.SignIn(model.Email, false /* createPersistentCookie */);
return RedirectToAction("Success");
}
else
{
ModelState.AddModelError("", Membership.Validator.ErrorCodeToString(createStatus));
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
And here is the paltry test I am trying to run...
[TestMethod]
public void Register_Post_ReturnsRedirectOnSuccess()
{
// Arrange
var controller = Mock.Create<Web.Controllers.MembershipController>();
var repository = Mock.Create<Membership.IMembershipService>();
Mock.Arrange(() => repository.RegisterMember("acceptible#email.com", "acceptiblePassword")).Returns(Membership.MemberCreateStatus.Success);
// Model
var model = new Web.Models.Membership.Registration
{
Email = "acceptible#email.com",
Password = "acceptiblePassword",
ConfirmPassword = "acceptiblePassword"
};
// Act
var result = controller.Register(model);
// Assert
Assert.IsInstanceOfType(result, typeof(RedirectToRouteResult));
}
The test fails because membershipService is resolving as null. I'm not sure what to do here. This is my first forray into the Unit Testing aspect of ASP.NET MVC. Can anyone give me some advice?
I am using Ninject to inject IMembershipService through the Constructor. It is implemented by the class MembershipService. The code runs fine when I run it, but the unit tests fail.
I don't see you passing repository anywhere into your controller. Normally you would have IMembershipService as a parameter in your controller's constructor that you can then pass in when needed or use MVC's Service Locator to grab the Ninject instance and pass it in.
:)