Creating Custom Assertions With Fluent.Assertions

FluentAssertions logo

I’ve been using Fluent.Assertions for years .NET, but until this week I had never looked into the community extensions. I started adding unit tests to a new controller I was creating in an existing ASP.NET Core MVC project, so I decided to take a look at FluentAssertions.AspNetCore.Mvc.

The primary use case I was unit testing was a controller that returned a ViewResult, but with two different status codes. On the happy path it would return a 200 OK, but if the user did not have the correct role it would return an error page with 401 Unauthorized. Unfortunately, there was no built-in assertion for the status code of a ViewResult.

Luckily, with extension methods we can easily add our own! I cloned the repo for FluentAssertions.AspNetCore.Mvc locally and took a look at how ViewResultAssertions worked. For example, here’s the WithViewName assertion. It tests that the name of the view to render matches the expected view name.

public ViewResultAssertions WithViewName(
    string expectedViewName,
    string reason = "",
    params object[] reasonArgs)
    var actualViewName = ViewResultSubject.ViewName;

        .BecauseOf(reason, reasonArgs)
        .ForCondition(string.Equals(expectedViewName, actualViewName, StringComparison.OrdinalIgnoreCase))
        .FailWith(FailureMessages.CommonFailMessage, expectedViewName, actualViewName);
    return this;

Using that as an example, it was straightforward to write an extension method to test the status code on a ViewResult. The highlighted lines show how to get the actual status code and then compare it using the FluentAssertions execution API.

public static ViewResultAssertions WithStatusCode(
    this ViewResultAssertions assertions,
    HttpStatusCode expectedStatusCode,
    string reason = "",
    params object[] reasonArgs)
    var viewResultSubject = (ViewResult)assertions.Subject;
    var actualStatusCode = (HttpStatusCode)viewResultSubject.StatusCode.Value;

        .BecauseOf(reason, reasonArgs)
        .ForCondition(expectedStatusCode == actualStatusCode)
        .FailWith("Expected status code {0}, but found {1}", expectedStatusCode, actualStatusCode);
    return assertions;

Nothing about this assertion is specific to my project, so I should take the time to submit it as a PR. After writing this, I even found that other result types, like JsonResultAssertion, have almost this exact implementation to check status codes.

The most exciting part to me though was seeing how nice the FluentAssertions execution API is. I’ll definitely be keeping an eye open towards creating my own custom assertion extension methods for repeated test patterns as I continue writing tests.

Dreyfus Model

Your brain on TypeScript

I recently started reading Pragmatic Thinking & Learning: Refactor Your Wetware by Andy Hunt. Very early in the book he describes the Dreyfus model, which provides a framework to think about how people attain and master skills. I thought it would be a good exercise to think through what stage I am at in various skills, especially since I’m absorbing so many new skills all at once at my new job at Husmus.

Stage 1: Novice

Novices are very concerned about their ability to succeed; with little experience to guide them, they don’t know whether their actions will all turn out OK. Novices don’t particularly want to learn; they just want to accomplish an immediate goal. They do not know how to respond to mistakes and so are fairly vulnerable to confusion with things go awry.

Pragmatic Thinking & Learning: Refactor Your Wetware by Andy Hunt

That all sounds very familiar to me and probably does to you as well. We’ve all had to work with a tool we don’t understand at all, but something is going wrong. We don’t have time to build a mental model of how the tool works; we just want to solve our immediate problem and move on. This was me with webpack a couple of weeks ago. I had no clue what I was doing as I customized my Vue build through Vue CLI. Knowing what to change and where was pure cargo cult programming at first.

This is also going to be as we build our engineering team at Husmus. I’ve done a lot of reading on building successful teams over the years, but that is very different from applying those skills. The good news is that I do have good team communication skills, but I’m definitely going to be a novice at managing the power imbalance.

Another good example is the image at the top of this blog post. I generated that using an AI art tool that I have no understanding of and probably never will. To me, it’s just a black box that I enjoy making silly pictures with. That particular one is Your Brain on Typescript.

Stage 2: Advanced Beginner

Advanced beginners can start to break away from the fixed rule set a little bit. They can try tasks on their own, but they still have difficulty troubleshooting.

Pragmatic Thinking & Learning: Refactor Your Wetware by Andy Hunt

This is where I actually am now with webpack and Vue CLI. I know how to customize what webpack is doing under the hood through vue.config.js. I understand how to use vue inspect to see the generated webpack file and where to hook in through vue.config.js to customize as needed. There are limits to my understanding of the underlying webpack config though. Without creating my own config from scratch I probably won’t be able to get to stage 3.

Another good example is Ruby on Rails. I haven’t done deep Rails work since 2012, so my skills have atrophied back to this stage. I was probably in stage 3 back then, but definitely back to stage 2 now.

Stage 3: Competent

At the third stage, practitioners can now develop conceptual models of the problem domain and work with those models effectively. They can troubleshoot problems on their own and begin to figure out novel problems – ones they haven’t faced before. They can begin to seek out and apply advice from experts and use it effectively

Pragmatic Thinking & Learning: Refactor Your Wetware by Andy Hunt

As a jack of all trades, master of none, this stage is my bread and butter. When I need to pick up a new skill, I often level up to this stage and then plateau because I need to move on to something else. Frustratingly, I would put my Docker skills at this level. I know how to do my day-to-day tasks, but it can be a struggle when I need to dig deeper. I’m at the point where giving myself a refresher course and going much deeper is necessary for me to get to stage 4.

Stage 4: Proficient

Proficient practitioners need the big picture. They will seek out and want to understand the larger conceptual framework around this skill. They will be very frustrated by oversimplified information

Pragmatic Thinking & Learning: Refactor Your Wetware by Andy Hunt

One of the defining characteristics of proficiency is being able to reflect and feed those learnings back into your conceptual framework. This perfectly describes my .NET skills. I don’t consider myself an expert, but I have the judgement to know what will and won’t work. Sometimes I can’t explain why and rely on intuition, which I’m getting better at accepting. Being able to reflect and work backwards to discover the root of that intuition is a skill I’m constantly working on though. This is essential when advocating for certain architecture choices that feel right to me, but I can’t consciously explain why off the top of my head.

Stage 5: Expert

Experts are the primary sources of knowledge and information in any field They are the ones who continually look for better methods and ways of doing things… These are the folks who write the books, write the articles, and do the lecture circuit.

Pragmatic Thinking & Learning: Refactor Your Wetware by Andy Hunt

I don’t consider myself an expert in anything and according to the Dreyfus model, you probably shouldn’t either. Only 1 to 5 percent of a population is an expert. So, while I think I’m a proficient .NET programmer, I don’t consider myself an expert. I don’t think I’ve reached that rarified air and I’m not sure if I ever will.

One caveat to this is domain knowledge. If you’ve been working in the same domain for many years and taken a keen interest in learning its ins and outs, then there is a reasonable argument that you are an expert in that domain. As a developer though, this definitely requires learning more than necessary for your immediate job and tasks.

Ownership and Intention

Husmus logo

tl;dr: I’m joining Husmus as their Director of Engineering.

I never expected to be in consulting for over a decade. When my wife and I moved to Richmond, IN in 2010, I didn’t really know what I was going to do. I got a job at a small local web shop and stumbled into a consulting career. When that job soured on me, I stumbled into being an independent consultant for about a year. Then I stumbled from there into an eight year stint at InfernoRed Technology.

I don’t regret how my career has gone, but it certainly hasn’t been intentional. Even my first job out of college was predicated highly on getting something as close to my now wife as possible. We were still two and a half hours apart, but that was way better than the distance we dealt with through college.

So, when I decided to start job hunting in April, this was really the first time in my career that I was searching for a new job with intention. I was still working, so I wasn’t under financial pressure to find something immediately. I was pretty burned out on consulting. I had spent a decade jumping from client to client, never feeling like I had any real long-term stake in the product or codebase. I knew that I wanted that to change, but wasn’t exactly sure what form that would take.

I ended up applying to twenty-one different companies. Initially, I was applying directly with most of them, but that shifted more towards recruiters over time, either in-house or external. There was definitely a tendency to focus on smaller product companies to try and get that sense of ownership I wanted. I also really wanted to get into Elixir more if possible, but that part didn’t end up working out.

Of those twenty-one, I had interviews with thirteen. In an approximately one and a half month window, I had thirty calls, both introductory calls with recruiters and more formal interviews. It was draining. Being able to work full-time while job hunting was definitely a privilege, but spending a couple of hours most nights reading job postings, writing cover letters, filling out applications, prepping for interviews, and completing take home exercises was a lot. I’m not going to miss any of that. Neither will my family. I greatly appreciate my wife’s patience over the past two months as she barely saw me in the evenings.

That’s a whole lot of background to get to announcing that I am joining Husmus as their first employee and Director of Engineering. Working for a very early stage startup was something on my radar when I started my search, but I didn’t actually expect it to pan out the way it did. I’m looking forward to having both literal ownership in the company and emotional ownership in what I’m building.

I greatly enjoyed my time at InfernoRed Technology and want to thank everybody there. I got to work with so many amazing people over the years. I knew that no matter the client, I could trust that everybody I worked with at IRT was going to get the job done. Not being able to sit down at my desk every morning and talk to them on Slack is something I’ll definitely miss.

And a huge thanks to the founders of IRT, Josh, Scott, and Art. Throughout my entire interview process they were open and supportive. It’s a sign of great leadership when they continue to support you and ask how they can help even as you’re trying to leave.

I’m looking forward to the next chapter of my career and making it the first one I’ve authored with intention.

How I Focus: Cold Turkey

Cold Turkey Blocker Logo

In my last post I talked about how I use Forest to stay off my phone when trying to focus. In fact, I just started a sixty minute block to help me focus while working on this post. However, that just keeps me off my phone. What about all the magical distractions the internet can offer as I write this on my laptop? For that I use Cold Turkey.

What Is It?

Cold Turkey is a distraction blocking tool. It gives me the power to fight against my tendency to fall down the internet rabbit hole and not actually get anything done. My capacity to get lost in Wikipedia (or YouTube (or Twitter)) is boundless. Cold Turkey prevents those tangents from even happening.

Block Lists

The core of Cold Turkey is its ability to block lists of websites and apps. I currently just have one list called Distractions, but you can define multiple lists if you prefer. You also have the power to add exceptions. For example, I block, but I’m also a YouTube Music user (R.I.P. Google Play Music). I’ve added an exception for so that I am still able to listen to music throughout the day.

One downside to how Cold Turkey works is that block list is based entirely on what is in your browser’s address bar. This means that I can still be distracted by YouTube videos embedded in sites or that get posted in Slack. Sometimes this is useful, but overall it’s more of a negative for me. I have used other tools in the past that modify your hosts file, but always ended up having issues. The downside of some stuff getting through is outweighed by having it work reliably.

The ability to block applications is also really helpful. My Mac currently doubles as my work and personal machine, so it’s helpful to block things like Steam and Discord during work hours. You can also block specific binaries or the contents of specific folders from running, but I haven’t needed to use that myself. Blocking things in just the Applications folder has been good enough so far.

Scheduled Blocks

I’ve worked remotely for over eight years now and one way I keep a strong separation between home and work is by working a pretty strict 8-4 schedule. Cold Turkey helps me out by supporting scheduled blocks. From 8-4 every day, my Distractions list is blocked.

It’s difficult for me to work around this. I have it locked down so that I cannot turn it off or remove anything from the list during this time. That’s important for me, because it reduces the temptation to make an exception just this one time.

I’m not limited to just the scheduled blocks though. I can also turn on a block for a period of time ad-hoc. I often do this during non-work hours when I’m trying be productive on something like a blog post.

Wait! It Costs Money?

Fry from Futurama telling someone to "shut up and take my money"

Yes. I’m a software developer and I believe that other software developers should be paid for their work. It takes time and effort to make a tool like this work reliably across operating systems as those systems change. Don’t be shy about paying for software that is valuable to you.

You can use the free version to get a feel, but application blocking and scheduled blocks are central to my usage. That’s easily worth $39 to me.


Cold Turkey Blocker is arguably the most important productivity tool I use. My capacity to be derailed by the many wonders the internet offers is immense. If, like me, you struggle to resist its siren call, then give Cold Turkey a shot.

How I Focus: Forest

Forest app icon

I have worked remotely from home as consultant for over eight years now. Keeping focus during work is a constant struggle for me. I’m endlessly inventive in coming up with new ways to distract myself from doing work when I don’t want to. One tool I use to combat this is Forest, a distraction blocking app for your phone.

Blocking Apps

The big selling point of Forest for me is the ability to block apps for up to three hours. By default, it locks you out of every app on your phone. However, I use the allow list feature to allow certain apps. For example, I use Remember the Milk to keep track of projects and todo lists. That is productive work I can do with my phone, so I allow it.

The app blocking used to have some serious issues on Android, but recent updates have made it very reliable for me on Android 10. It used to get confused by notifications and and fail block timer. That is no longer an issue for me. I have no experience using it on iOS, so your mileage may vary.

Pretty Little Trees

Screenshot of weekly progress in Forest app
Some of these things may not appear in an actual forest.

My kids love how Forest gamifies staying off my phone by encouraging me to plant an adorable forest. For every 30 minutes you stay off your phone with a timer running you get a new tree. They love to see what I’ve grown recently and they even encourage me to grow more trees. That’s a win-win for them. They get to see more pretty trees on my phone and I’m not distracted by my phone, helping me be a more attentive father.

You earn coins every time you successfully complete a block, which you can then use to unlock different types of trees and bushes. The art style is whimsical and they’re not afraid to veer into things that are tree-adjacent at best. For example, the screenshot above has both candy and spirit trees alongside more realistic plants like apple trees and sunflowers.

Other Features

There are some features that might be useful to others that I do not use.

First, they have a Chrome extension to block websites. I use Cold Turkey Blocker for this, so I haven’t tried the extension. It seems worthwhile to try though if you like Forest and don’t currently use any other website blocking tools.

Second, you can go nuts with tags and notes on your block sessions if you like. I tried to do this a bit. I had tags for work, reading, side projects, etc. I constantly forgot to use it though, so my data was a mess. I gave up on it, but if keeping track of historical data is your thing then this feature is for you.

Finally, you can spend your virtual coins to plant real trees. Forest partners with Trees for the Future for this. I appreciate the sentiment, but I’m skeptical of the effectiveness of this kind of activism. It’s there if you want it though.


Forest is an important part of how I work on a daily basis. The combination of my phone being upstairs and an effective blocking tool even if I go upstairs keeps me off my phone when I’m trying to be productive. And the flexibility of the allow list lets me use my phone strategically when I need it for productivity. Plus, the in-app Forest you grow is adorable. If you, like many, are struggling with phone distractions, give Forest a try.