mercredi 1 juillet 2015

Unit testing with Jasmine, mocking a constructor

I'm unit testing JavaScript with Jasmine and I am running into some problems.

I have a large file to test and it has a lot of dependencies and those dependencies have their own dependencies. Because of said dependencies I want to mock all I can. There lies the problem. How can I mock a constructor so that it includes the methods that belong to it?

Lets say I'm testing a method createMap of class Map:

In that createMap method it calls for Layers class constructor using

var layers = new Layers()

I'm spying on it using

spyOn(window, 'Layers').and.callThrough()

That works fine but later in the createMap method it calls for layers.addLayer() where addLayer is a method of Layers class. Problem is that because I mocked the Layers call it doesn't recognize the addLayer method.

Is there a way to mock it so that it includes all the methods of the called class or is my only option to stub the whole Layers class or not mock it?

Or what would be a good way to handle this? I've tried to spyOn(Layers, 'addLayer') but there it says that no method addLayer is found.

I'm sorry if it's confusing a bit. I had trouble thinking how should I ask it.

Testing non-scope functions in Angular Controller with Jasmine

Jasmine is one of the most widely used testing frameworks to unit-test javascript code in BDD manner. I tried to use it for AngularJS components testing. AngularJS documentation provides the following sample code

describe('PasswordController', function() {
  beforeEach(module('app'));
  var $controller;

  beforeEach(inject(function(_$controller_){
    $controller = _$controller_;
  }));

  describe('$scope.grade', function() {
    it('sets the strength to "strong" if the password length is >8 chars', function() {
      var $scope = {};
      var controller = $controller('PasswordController', { $scope: $scope });
      $scope.password = 'longerthaneightchars';
      $scope.grade();
      expect($scope.strength).toEqual('strong');
    });
  });
});

So the code above uses angular mock library and via dependency injection processes a scope through a controller. Now I have a scope object with functions and objects my controller assigned to it. I can test it well. Happy.

Now the interesting part is if I want to test the functions which are not linked to the scope. For example, the doSomethingVeryCoolThatNeedsTesting function below

angular.module('app', [])
.controller('PasswordController', function PasswordController($scope) {
  $scope.password = '';
  $scope.grade = function() {
    var size = $scope.password.length;
    if (size > 8) {
      $scope.strength = 'strong';
    } else if (size > 3) {
      $scope.strength = 'medium';
    } else {
      $scope.strength = 'weak';
    }

   function doSomethingVeryCoolThatNeedsTesting() {
    ....  
   }

  };
});

It seems that whenever I use $controller('PasswordController', { $scope: $scope }); it returns a populated $scope object and undefined controller object.

TL;DR

Is there a way I can test Angular Controller functions which are not linked to the scope?

clojure unit-testing with-redefs

I have something like this:

(ns server.core
  (:require [db.api :as d]))

(defrecord Server [host port instance]
  (start [c]
    (let [connection (d/connect (:host c) (:port c))]
      (assoc c :instance connection)))
  (stop [c]
    ;; close the connection
    ))

(defn new-server
  [host port]
  (map->Server {:host host
                :port port}))

And the unit-tests code

(ns server.core_test
  (:require [server.core :refer :all]
            [clojure.test :refer :all]))

(deftest server-test
  (testing "Calling start should populate :instance"
    (with-redefs [d/connect (fn [h p] [h p])]
      (let [server (start (new-server "foobar" 12313123))]
        (is (-> server :instance nil? not))))))

Running the code above with boot watch test throws an error similar to:

Unable to resolve var: d/connect in this context

And then I modify the test code so it requires the db.api

(ns server.core_test
  (:require [server.core :refer :all]
            [clojure.test :refer :all]
            [db.api :as d]))

I ran the tests again, this time d/connect still refers to db.api.

Any advice guys?

sails js unit testing

I have creted a sails js application. I want to add unit testing for my application. I am using following approach to do the unit testing. http://ift.tt/1CIKZDS

I am using grunt to test my application with mocha. Now I need a way to override some sails methods (find, update, etc. ) to use for my testing, since I do not want interact with the database when testing the code. Is there a way override sails js methods. As an example when I use User.find method in my testing, I want to have a specific result to test my other methods work perfectly. Any kind of help would be appriciated.

.Net, Specflow, AngularJS, and Saucelabs

So I'm trying to get all testing running through a single framework and wondered if anyone has figured out how to do this yet.

Using .Net framework with Specflow (aka cucumber for .net) and able to run c# unit tests, tsqlt unit tests(through a c# wrapper), end-to-end tests through protractor.net... The only thing I'm not sure about is how to get straight angularjs unit tests to run.

Any ideas? C# wrapper for jasmine to make it work with Specflow?

Or would it be better to just leverage cucumberjs itself (and maybe protractorjs as well as the syntax looks cleaner) and I think I'm going to be running these in saucelabs and doing that from one framework seems easier.

Thoughts?

Did I find a java.util.Calendar bug?

I have the following test:

import static org.junit.Assert.assertEquals;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.TimeZone;

import org.junit.Test;
public class CalendarBug {
    private static final TimeZone UTC_ZONE = TimeZone.getTimeZone("UTC");// +0 hours
    private static final TimeZone IST_ZONE = TimeZone.getTimeZone("IST");// +5 hours 30 minutes

    @Test
    public void calendarBug() {
        Calendar utcCalendar = Calendar.getInstance(UTC_ZONE);
        utcCalendar.set(Calendar.YEAR, 2015);
        utcCalendar.set(Calendar.MONTH, 3);
        utcCalendar.set(Calendar.DAY_OF_MONTH, 12);
        utcCalendar.set(Calendar.HOUR_OF_DAY, 10);
        utcCalendar.set(Calendar.MINUTE, 0);
        utcCalendar.set(Calendar.SECOND, 0);
        SimpleDateFormat utcFormatter = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss Z" );
        utcFormatter.setTimeZone(UTC_ZONE);
        System.out.println( "If I have this line commented out, the test fails: " + utcFormatter.format(utcCalendar.getTime()));
        Calendar istCalendar = (Calendar) utcCalendar.clone();
        assertEquals(UTC_ZONE, istCalendar.getTimeZone());
        istCalendar.setTimeZone(IST_ZONE);
        assertEquals(istCalendar.getTimeInMillis(), utcCalendar.getTimeInMillis());
    }
}

If you run the test, it works. However if you comment out the System.out.println line with the formatter inside, it fails:

java.lang.AssertionError: expected:<1428813000979> but was:<1428832800979>
    at org.junit.Assert.fail(Assert.java:93)
    at org.junit.Assert.failNotEquals(Assert.java:647)
    at org.junit.Assert.assertEquals(Assert.java:128)
    at org.junit.Assert.assertEquals(Assert.java:472)
    at org.junit.Assert.assertEquals(Assert.java:456)
    at xxx.yyy.CalendarBug.calendarBug(CalendarBug.java:29)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

It seems that the formatter changes the internal state of the utcCalendar and it causes the test to pass.

Did I misuse anything here? Is there an open bug in JDK for this?

Java version:

liptak@XXXXXX:~$ java -version
java version "1.7.0_60"
Java(TM) SE Runtime Environment (build 1.7.0_60-b19)
Java HotSpot(TM) 64-Bit Server VM (build 24.60-b09, mixed mode)

Unit tests in Visual Studio 2015 RC can not run

I created a unit project (windows 10 universal) and when I run a test method like:

[TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestMethod1()
        {
            int x = 1;
            Assert.AreEqual(1, x);
        }

    }

The test will not run:

enter image description here