Ryan Heathcote Engineer. Teacher. Dreamer.

Important Nuance of Spock Testing

I was having some trouble yesterday with a mock invocation that wasn’t catching. After some experimentation with a wrong idea, I decided to look at the Spock documentation on Interaction Based Testing. I very quickly came across the solution to my woes:

all invocations on mock objects that occur while executing the when block will be matched against the interactions described in the then: block.

This innocent-seeming phrase is vitally important.

Consider the following code (I’ve simplified it for demonstration purposes):

class A {
    isValid() { 
        //some validation code 
    }
}

class B {
    A a

    B(A a) {
        this.a = a        
    }

    isAValid() {
        a.isValid()
    }
}

This is a silly example, of course, but the kind of situation where you would have this structure is when A is an object whose validity depends on several conditions, of which one of those conditions has a significant amount of complexity, which you have abstracted into B. One advantage of this abstraction is that you can now mock B rather than have to test around all the complexity that would have remained in A if you had not abstracted it.

The first attempt I made at testing this structure was this: (I made this attempt because spock mocks require when: and then:, and I only wanted to use expect:).

class BSpec extends Specification {
    
    void "test isAValid"() {
        setup:
        A mockA = Mock()

        when:
        B b = new B(a)

        then:
        b.isAValid()

        and:
        1 * mockA.isValid() >> true
        0 * _

    }
}

But this will not work. I could not understand why, until I read the abovementioned sentence. It is the b.isAValid() method that invokes the a.isValid() method, and that is being called in a then: block, after Spock is done tracking invocations. Deceptive, yet quite simple. I was trapped by my assumption that I wanted my b.isAValid() to assert on its own, and therefore would need to be in the then: block. Of course, the easy way around that is to just store the result of the call in a variable. A little more verbose, but at least it works. ;)

So all you have to do to make the test pass is:

class BSpec extends Specification {
    
    void "test isAValid"() {
        setup:
        A mockA = Mock()

        when:
        boolean result = new B(a).isAValid()

        then:
        result

        and:
        1 * mockA.isValid() >> true
        0 * _
    }
}

So there you have it. If you have a Spock mock invocation that just won’t catch, and you don’t see any reason in your code why it shouldn’t be happening, take another look and see if you have your mock-invoking calls coming from the then: block… If so, you haven’t landed in a parallel universe where code doesn’t compile properly, you just need to reorder your code.

Happy coding, and keep it Groovy, everybody!

QueryString Parameters and the Aurelia Router

This post forms an attempt to show a process of thinking through a problem, not just the solution. I think the process will be helpful to younger programmers. And maybe to more experienced programmers who want to see the intermediate steps to the solution, not just the solution. I also hope it encourages more programmers to look at the source code of libraries they use.

I’ve been fiddling with some Aurelia Code. I basically want to be able to append a parameter to the route without having to reconfigure the route. In other words, I want to be able to do router.navigate('/bookLists/24?page=2) – that is, specify a page on a bookList. But I have multiple pages on my application that will use pagination, and I don’t want to have to reconfigure the route for each of them to have a page parameter. So I was a little confused.

Which brings me to an aside:

I have a growing disdain for reading documentation. Most of the time I find documentation (even good documentation) leaves me feeling confused, and uncertain if my edge case will work. I find a growing tendency to look at source code for answers to questions I have about how to use certain libraries. I think this is part of a broader thought: In this world, far too much time is spent regurgitating information. The Internet is a vast library of the world’s information, but a quick google search for an interesting topic will often reveal that much of that information is simply duplicating what Wikipedia says. If you combine that with a growing distrust of almost all media outlets, I think you find that there is a growing need to go to the source materials. In the case of the media, read the transcript of a speech given by the French President, rather than what a news article says about the speech. In the case of software development, read the source code of the library you are using, rather than trying to parse the (most likely) incomplete documentation.

Aside over, I did that with the aurelia router, because none of the google searches I could generate gave me results that actually answered my question. (Full disclosure: I think my google-fu is fairly poor). So I broke down and read the source of the aurelia-router. Very quickly I was able to isolate the method that interested me:

navigateToRoute calls generate to get a path that it can use in calling navigate:

  navigateToRoute(route: string, params?: any, options?: any): boolean {
    let path = this.generate(route, params);
    return this.navigate(path, options);
  }

After doing some other (mostly irrelevant) stuff (well, I mean we can tell that it basically looks up the route, and if it can’t find it, calls up to a parent router to check if the parent router has a route that matches our attempted navigation, and if nothing comes out of that, we say “Oh no, I can’t find a route!”), the generate method uses the _recognizer’s generate method, before generating a rootedPath which I presume to be something that you can actually set window.location.href to. But that’s not relevant to my question. Also, note that the use of the options parameter appears to relate exclusively to the absolute option, which is irrelevant to what we are doing. The only thing that is relevant is this _recognizer stuff.

  generate(name: string, params?: any, options?: any = {}): string {
    let hasRoute = this._recognizer.hasRoute(name);
    if ((!this.isConfigured || !hasRoute) && this.parent) {
      return this.parent.generate(name, params);
    }

    if (!hasRoute) {
      throw new Error(`A route with name '${name}' could not be found. Check that \`name: '${name}'\` was specified in the route's config.`);
    }

    let path = this._recognizer.generate(name, params);
    let rootedPath = _createRootedPath(path, this.baseUrl, this.history._hasPushState, options.absolute);
    return options.absolute ? `${this.history.getAbsoluteRoot()}${rootedPath}` : rootedPath;
  }

A quick find in the code reveals that the _recognizer gets set in the reset method which is also called by the constructor:

    this._recognizer = new RouteRecognizer();

So now we ask, what is a RouteRecognizer?

import {RouteRecognizer} from 'aurelia-route-recognizer';

Oh, another library. Google finds me the aurelia/route-recognizer repository (my google-fu isn’t that bad).

We want specifically to look at the generate method of the recognizer, and guess what I find in the DocBlock? The answer to my question! If you pass in extra parameters, they’ll be dropped on the querystring! :)

/**
  * Generate a path and query string from a route name and params object.
  *
  * @param name The name of the route.
  * @param params The route params to use when populating the pattern.
  *  Properties not required by the pattern will be appended to the query string.
  * @returns The generated absolute path and query string.
  */
  generate(name: string, params: Object): string {

One more thing – is this comment out of date? Remember, the code is what runs on a system, not the comments, so don’t trust them too far. (I won’t belabor the point by exhaustively proving that this is actually done). Here’s the relevant fragment to substantiate the comment’s claim:

    // remove params used in the path and add the rest to the querystring
    for (let param in consumed) {
      delete routeParams[param];
    }

    let queryString = buildQueryString(routeParams);
    output += queryString ? `?${queryString}` : '';

    return output;

So now I know that if I want to call a route that has parameters, but I want to add extra ones, I can trust they will hit the query string. Or in other words, router.navigate('#/books/24?page=2') should be equivalent to router.navigateToRoute('books', { id: 24, page: 2}). Much more flexible. :)

As a last aside:

This whole exercise demonstrates the value of code that is clear. Because of the clarity of the aurelia code, I was able to answer a fairly involved technical question simply by looking at the code, without having to call one of the project’s developers to ask my question. But you’ll notice, apart from some very terse docblocks, the aurelia code is largely lacking in comments. It’s clear enough that you don’t need comments. I generally believe this to be the best way to go, because human nature all to easily changes code without changing even the comment one line above, thus creating a situation of conflicting information. Better to let the code explain itself than try to explain code today in a way that will confuse another programmer 6 months from now because your comment no longer reflects reality after you made “a quick change to test something” and forgot to change the comment once your test worked. Also remember that you yourself will essentially be “Another programmer” 6 months from now…

Coding Experiments

I’ve added a new section to my site for coding experiments. Mostly these are just random html pages that I’ve thrown together to experiment with some strange and wonderful html thing. Head over to the My Coding Experiments to see what I’m talking about. The first one is a fun sliding bars experiment. But I’ll hopefully add a couple more shortly.

Bitbucket Pipelines adds Dependency Caching

At my company we’ve been using Bitbucket Pipelines for automated builds for about a year now. After migrating away from Bamboo, the simplicity and flexibility of Pipelines is quite refreshing. I love building with Docker images, and being able to keep the build configuration in the same source code as the application. That means the build configuration is versioned along with the application, and there is all sorts of other goodness.

One minor annoyance that I’ve encountered is that we have to install packages every time. Our application uses maven (for Grails 2), npm, and jspm, so there’s a lot of downloading before any normal build can run, and its 99% redundant. I’ve thought about trying to pre-install packages on the Docker image we use for our build (which is already custom because we’re using two very disparate language stacks in the same repo), but it just seemed a little too complicated – and besides, it would either require writing another automated build to build the Docker image every time the dependencies changed, or just remembering to do it and still have to run the installers to update things every time.

Today, I hit the point where I just wanted to find a solution to this problem. For one thing, waiting for builds to finish wastes a lot of my own time. And gives me windows to become distracted by interesting articles or fun projects. Another fairly big thing is that we ran out of build minutes this month. They aren’t expensive, but we use a lot of build minutes, and a lot of that time is spent downloading packages, so it would definitely be a double win to cache the dependencies – save my time, and save build minutes.

I was wrestling through the different ways I could implement it myself, when I came across an article about Bitbucket Dependency Caching, and thought “How have I not heard of this before?” Well, as it turns out, they just added it – in June of this year. The documenation for their dependency caching feature is pretty straightforward. So I tested it out, and within minutes had our maven dependencies configured. I had to go with a custom definition for the node and jspm packages as they are in a subfolder. Nonetheless, it was quite quick and painless, and solved a pesky problem for me without me having to write any code myself, or create a funky custom two-stage build.

I’ve been quite impressed with Bitbucket Pipelines since we started using it, and this feature is just another example of how it just keeps getting better. :)

Liberty University GenCyber Summer Camp

I am teaching Linux Security again this year at Liberty University’s GenCyber Summer Camp. The camp involves taking 36 High School students divided into teams, each of which is given network of servers to administer. Their networks feature both Linux and Windows Operating Systems, various web applications (as diverse as WordPress, Gitlab, and Jenkins), and an OpenSense Firewall, configured insecurely to provide a significant challenge to the students. We spend 4 days teaching the students some Information Security theory, and as much as we can about securing all their servers, before they are subjected on the last day to a live attack by a Red Team of professional penetration testers. It makes for an intense week of drinking from a firehose for the students, and creative thinking for the instructors. At the same time, being presented with a seemingly insurmountable challenge often results in the best fun human beings can have.

I taught the Linux security section of the course last year, so this year I’ve made a bunch of improvements on my lesson based on books I’ve read on teaching, and the lessons learned from last year’s overwhelming Red Team success. We instructors are hoping this year we can actually make life challenging / interesting for Red Team. If you are curious what my materials look like, or if you are a student, go to my lessons for the camp.