Pages

Sunday, November 27, 2016

How to Bypass the New Microsoft Office Startup and Save Screens

Starting with Office 2013, there are two changes that some people will like and use, but that I hate and don't.

Startup Screen

I rarely need to open a template other than the blank one. However, the default Office behavior is to show a Van Gogh Starry Night of choices.

image

Do this to disable the new startup screen and go immediately to a blank document, as it has been for two decades. Instructions are for Word 2016.

  1. Open Word
  2. Open a blank (or existing) document
  3. Choose File > Options
  4. In the General > Start up options, uncheck "Show the Start screen when this application starts"
  5. Click OK. Word now opens to a blank document.

image

Backstage View (Save Screen)

Microsoft OneDrive is intended to be deeply integrated into MS Office. Microsoft wants you saving there by default. The Save screen reflects that when you save a new document (or Save As an existing one).

image

However, many people prefer to save locally, even if that means saving to the local OneDrive folder for later synchronization.

Do this to show the file Save As dialog that you've seen since raptors tried to eat your computer.

  1. Open Word
  2. Open a blank (or existing) document
  3. Choose File > Options
  4. In Save > Save documents, check "Don't show the Backstage when opening or saving files"
  5. Click OK. Save/Save As shows the good, old dialog.

image

Hello, old friend.

image

References

http://www.howtogeek.com/tips/how-to-bypass-the-backstage-view-when-saving-new-files-in-office-2013/

Tuesday, November 22, 2016

Google Tasks vs Reminders in Desktop and Phone

Google appears to be transitioning away from their dedicated Tasks app. This doesn't surprise me, as Tasks always seemed bolted on and only useful in the most minimal way, though some people--such as my wife--have used it effectively.

The general challenges of tasks are that they're more complex than people imagine. Some potential features:

  1. Scheduled vs non-scheduled tasks.
  2. Scheduled for anytime during the day, or for a time ("due by").
  3. Sub-tasks.
  4. Categories/tags.
  5. Movement (or not) of completed items to the bottom of the list.
  6. Clearing (or not) of completed items.

Google provides some reasonable task management apps.

Task Replacements

The two replacements for Tasks are:

  1. Keep
  2. Reminders

Tasks and Reminders work differently depending on whether you're using a desktop browser or your phone, which I'll detail later.

In Tasks, a task could be assigned a date, or "no due date." These loosely equate to...

  • Keep (no due date). Keep lets you create notes of checked lists. While Keep doesn't let you assign dates to a particular note's list item, it does let you set a reminder on a note.
  • Reminders (due date), which show on the Google Calendar for a particular date and, optionally, time.

Here's a Keep note with reminder dialog. You can also set location-based reminders, handy for a note like "drop off book to Sam."

image

And, here are two Reminders, from the desktop Calendar. One is "all day," the other is for 9am.

image

On the Desktop: Using Tasks OR Reminders

When accessing the Google Calendar from your desktop browser, you can view either Tasks or Reminders, but not both at once. Each is really a (somewhat) hidden calendar. To switch, click the down-arrow next to the Reminders (or Tasks) calendar under My Calendars.

image

When Reminders is selected, you'll see them as shown above. When Tasks is selected, you'll see a new sidebar, and scheduled tasks appear on the calendar.

image

There is a way to view Tasks in your browser without using Calendar. You use the same URL that your phone uses (see below). But who knows how long this will be available?

https://mail.google.com/tasks/android

 image

On the Phone: Viewing Tasks--but not Reminders--in the Browser

In Android (and probably iPhone), you can use the phone's web browser to access Gmail, the Calendar and Tasks. To view Tasks, go to:

https://mail.google.com/tasks

When the page loads, you'll see your tasks, regardless of whether you've chosen to view Reminders or Tasks in your desktop calendar. (As shown above, you can get to this same view from the desktop, using a slightly different URL.)

image

If you dropdown the "More" button, you can also view the Calendar. However, you will not see Tasks or Reminders, and I don't see a way to enable viewing them.

image

On the Phone Again: Viewing Reminders in the Calendar App

In the Calendar app, you can enable or disable showing Reminders, just as you would any other calendar. However, you cannot switch to the Tasks calendar. As far as I can find, there's no way to view Tasks using the Calendar App.

image

Here's a look at those Reminders.

image

Wrap Up

Google's Tasks are heading the way of the dodo, supplanted by Keep notes, and calendar Reminders. To summarize:

Desktop

  • In Google Calendar, you can toggle between either Tasks or Reminders.
  • If you want to be clever, you can set your Calendar for Reminders, and view Tasks at https://mail.google.com/tasks/android

Phone


Notes

* The difference between a task and an event? A task is something you do, an event is somewhere to be.


References

Google Tasks Help

Sunday, November 6, 2016

Catching Up on Coding - Claims-Based Identity Part 1

the-magician

I’ve been a software developer for twenty years, but am behind in some skills. This series chronicles my self-improvement.

Claims-based identity isn't hard to understand, but it's been challenging to learn and implement in a legacy environment. In part one, we'll look at the concepts. In future posts, I'll have code samples using current (at the moment) frameworks.

Like Tony Blake producing a flock of doves, we'll learn some security sleight-of-hand.

Previously on CUOC: TDD Part 3
Next Episode: Claims-Based Identity Part 2

 

 

 

Claims-Based Identity Basics

What We're Used To - Passwords

The convention in authentication for decades--for millennia, in a sense--has been this exchange:

"Let me in."
"What's the password?"
"Swordfish."

You're allowed in because you know something only a few people should: the password. Once you're in, the exchange continues.

"I want to see the boss."
"Oh yeah? Who's asking?"
"I carry packages for Don Crosetti."
"A courier? Delivery boys don't see the boss, chum."

What you get to do is defined by your role. A lieutenant can see the boss. A courier can't.

This is very much how people understand software security to work. You enter a username and password on a web site, let's say a Content Management System. Once in the site, if you're a Viewer, you can look at all the pages but not edit anything. An Blogger can create posts for her own blogs, but not anyone else's. A Site Editor can modify anyone's posts.

This system works well enough for many situations (in both software and life). But there's another common approach: claims.

What We're Also Used To - Claims

It's Friday night and you go out to a dance club. To get in, you have to show your driver's license. The guy at the door looks it over, then waves you in. What was he checking? Two things.

  • Were you over 21?
  • Did the license look valid for the issuing state?

The first item is a claim. You're claiming to be over twenty-one. You have a driver's license issued by a recognized identity validator: the Bureau of Motor Vehicles. The doorman didn't verify your identity. He didn't ask for a social security card or birth certificate or fingerprints. He trusts that the BMV did all that. The most he did was check that the license was the expected color and had the right hologram.

As long as he trusted the license, he trusted the claims on the license: your birth date, name, height, weight, etc.

Roles can be claims: maybe at this particular club you have a VIP card that lets you into the upper floor. However, claims are not necessarily roles. Claims can allow more fine-grained and nuanced authorization.

There are two important aspects of this example:

  1. The bar didn't ask for a password. They trusted a third party's identity authentication.
  2. The bar authorized entry based on a claim, not a role.

With those two real-world examples in mind, we're ready to look at claims-based identity in software.

What's an Identity Provider (Security Token Service)?

In the bar example, the identity provider is the BMV.

An STS takes care of authenticating identity, if needed, and returns a token than contains claims about the identity. An STS could be local or remote. Examples include:

  • A local database containing user and password hashes.
  • A local Active Directory
  • Azure Active Directory
  • Google

What's a Token?

In the bar example, the token is the driver's license.

A token is just data about the identity and issuer. It could be an XML document, for instance. Generally speaking, it can have:

  • A unique ID
  • An issuer certificate id
  • A collection of claims

What's a Claim?

In the bar example, the claim is the age.

A claim is a fact about the identity (i.e., the user). A claim is trusted if the identity provider is trusted. Claims could include:

  • Name
  • Email
  • Date of Birth
  • Country

What's Federated Identity?

The word "federation" means "union by agreement."

A body formed by a number of nations, states, societies, unions, etc., each retaining control of its own internal affairs. [Dictionary.com]

When it comes to identity, otherwise unrelated organizations can trust each other's STSs, allowing a user to log in with one set of credentials that are accepted elsewhere. This forms the basis of single sign-on (SSO).

A simple example of real-world federation would be a background check company that wants to give its customers access to their reports without storing them as users. The company would:

  1. Set up a federated STS.
  2. Establish a trust with the customer's Active Directory (for example).
  3. The customer determines which AD claims to provide.

A customer's user would log into their computer using their corporate credentials. When she opened the background check web site, the site would check if there was an authenticate token, and find the user's credentials in a cookie (perhaps). The web site would contact the STS, which would contact the customer's AD and verify the token's validity and return claims. The site would then authorize access if the claims allowed.

At no time did the user retype credentials.

Simplest Steps of Getting Authenticated Claims - Code Neutral

Here's some pseudo-code (C# style) showing how an application might get and use a claims token. Note: These are not real .Net classes!

A simple user.

class User
{
    public string Email { get; set; }
}

The claims class. (The real .Net class is just about this simple.)

class Claim
{
    public string Type { get; set; }
    public string Value { get; set; }
}

A token/identity class, which contains a collection of claims.

class IdentityToken
{
    public string TokenId { get; set; }
    public IEnumerable<Claim> Claims { get; set; }
}

A helper class that checks authentication status.


static class AuthenticationManager
{
    public static bool IsAuthenticated(User user)
    {
        bool authState = false;
        //check a cookie, or database, or session state, etc.
        return authState;
    }

A provider service to handle getting the token. This is the complex part if you wrote it yourself, since it needs to properly manage the network connection, protocol, certificates, trust, etc.

class Provider
{
    public string SignOnUri { get; set; }
    public string ProviderId { get; set; }
    public string ApplicationId { get; set;}
    public IEnumerable<Claim> GetClaims(string email)
    {
        //Set up network connection, such as to a remote Azure AD server
        var connection = GetConnected();
        //The provider knows which applications are allowed.
        if (!connection.IsValidApp(applicationId)) { throw new Exception("Invalid app");}
        //The user might need to sign in via a remote page NOT on our site.     
        var response = connection.Authenticate(email, SignOnUri);
        if (response.Authenticated)
        {
            //The framework-specific provider takes care of the messy work of parsing the claims.
            var claims = new List<Claim>();
            foreach (string clm in response.TokenClaimCollection)
            {
                claims.Add(new Claim() { Name = clm.Identifier, Value = clm.ValueUri }
            }
            var token = new Token() { TokenId = response.TokenGuid, Claims = claims};
            //store the token info somewhere, like in a cookie or database
            Session.Store(token);
            return token.Claims;
        }
        else
        {
            throw new Exception("Not a valid user.");
        }
    }
}

And here's how authentication might look, using that provider.

void Main()
{
    //The user who wants access.
    User user = new User() { Email = "jane.doe@example.com" };
    //We have a class that checks if the user's authenticated.
    if (!AuthenticationManager.IsAuthenticated(user))
    {
        //Set up a service class that does the work of communicating
        //with the STS. Behind the scenes, it could use WS-Federation, OpenId, SAML, etc.
        var sts = new Provider()
        {
            SignOnUri = "https://login.otherplace.com",
            ProviderId = "ef26632f-9af6-4ea0-8fcc-a8cee466cb6d",
            ApplicationId = "mysite.mydomain.com/isunique"
        };
        //Get the claims collection in our format. If we get this without error,
        //the user was authenticated. We don't care how! This is where the user
        //might be redirected to a login page.
        var claims = sts.GetToken(user.Email).Claims;
        //Check if the user can do something
        if (claims.First(c => c.Name == "Company").Value == "XyloTech")
        {
            //Show their reports
        }
    }
}

In the above method, we

  1. Found the user wasn't authenticated
  2. Instantiated our identity provider. This included a way to verify to the provider who we were, and vice versa. (Note: technically, the application trusts the STS, but the STS doesn't trust the application.)
  3. Asked the provider to authenticate the user. We may not know or care how this happens.
  4. Got back claims. Our provider class did the messy work of converting it to our class collection.
  5. Checked for a specific claim and took action.

In the next post, we'll look at some of the various namespaces Microsoft uses for claims-based identity.

--------------------

Tony Blake's Corvette, license plate: "SPIRIT"

image

Saturday, October 22, 2016

Creating Forms Authentication Membership Tables in LocalDB–Right and Wrong Ways

The Problem

There’s a rare chance these days that you’ll need to manually create the authentication tables used by the old ASP.NET WebForms Forms Authentication Membership Provider. The tool to do this is aspnet_regsql.exe , found in the .Net Framework folders.

Even rarer will be using the tool to create the tables in LocalDB. You don’t really have to. The database will be automatically created, even in Visual Studio 2015, if you do the steps at the end of the article.

The Wrong Way

But let’s say you do use the tools, as in this command line for Windows 64-bit.

%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_regsql.exe -E -S (LocalDB)\v11.0 -d aspnetdb -A mr

Assuming you have the SQL 2012 LocalDB installed, running the above will create a file in your user profile named aspnet.mdf, for example C:\Users\charles\aspnetdb.mdf.

Here’s the rub. If you delete the file, then run the command again, you’ll get this error.

An error occurred during the execution of the SQL file 'InstallCommon.sql'. The SQL error number is 5120 and the SqlException message is: Unable to open the physical file "C:\Users\charles\aspnetdb.mdf".

This happens because LocalDB is still storing an entry in sys.databases (in the master database) for the database you just created. In my opinion, it shouldn’t, but what do I know?

Cleaning Up from the Wrong Way

To remove this entry, you need to delete the entry by connecting to LocalDB like a server. These instructions show using Visual Studio’s database tools, but the steps are similar for SQL Management Studio.

  1. Open Visual Studio
  2. You don’t need to create a project. Just Tools > Connect to Database.
    image
  3. Choose Data source = Microsoft SQL Server
  4. Enter Server name = (LocalDB)\v11.0
  5. Drop down the list of databases. You should at least see master, etc.
    image
  6. You will not see aspnetdb. Choose the master database.
  7. Open the Server Explorer, right-click the connection and choose New Query.
    image
  8. In the query window, enter and run:
    select * from sysdatabases
  9. You’ll see aspnetdb listed.
    image
  10. Run this command:
    drop database aspnetdb
  11. You’ll get an error message:
    Unable to open the physical file "C:\Users\charles\aspnetdb.mdf". Operating system error 2: "2(The system cannot find the file specified.)".
    File activation failure. The physical file name "C:\Users\charles\aspnetdb_log.ldf" may be incorrect.
  12. But that’s OK. If  you select from sysdatabases again, you’ll see the aspnetdb has been removed.
    image

Creating the Database the Right (Easy) Way

I didn’t find documentation saying I could do this, and tried it on a whim. Basically, if you configure your project to use a LocalDB as your membership provider, the first time the app tries to use it the database will be created with the correct tables. At least, this is true in Visual Studio 2015.

Add Old-Style Forms Authentication

Web.Config

Open web.config. Under <configuration>, add this connection string.

  <connectionStrings>
    <!-- ASP.NET MembershipProvider-->
    <add name="ASPNETDB" connectionString="Data Source=(LocalDB)\v11.0; Integrated Security=true;AttachDbFileName=|DataDirectory|ASPNETDB.mdf" providerName="System.Data.SqlClient" />
  </connectionStrings>

In <system.web>, add this.

     <!--ASP.NET MembershipProvider, must be None for other providers such as OWIN-->
    <authentication mode="Forms">
      <forms loginUrl="~/" timeout="2880" />
    </authentication>
    <membership defaultProvider="AspNetSqlMembershipProvider">
      <providers>
        <clear />
        <add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="ASPNETDB" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="/" />
      </providers>
    </membership>
    <!--Set enabled to false for OWIN-->
    <roleManager enabled="true" defaultProvider="AspNetWindowsTokenRoleProvider">
      <providers>
        <clear />
        <add name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="ASPNETDB" applicationName="/" />
        <add name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider" applicationName="/" />
      </providers>
    </roleManager>

Create the Membership Database

In Default.aspx.cs

Add these using statements.

//MembershipProvider (forms authentication)
using System.Security.Principal;
using System.Web.Security;

In some part of your app’s startup, add this code, which we'll run once to create the database, add a user, and add a role. For example, this could go in a Web Form’s Page_Load, in a Controller action, or in a console app’s Main. You could, of course, not create a role, or delete the user afterward, etc.

            string email = "charles@aspnetmembership.com";
            string role = "Dev";

            Membership.CreateUser(email, "BadPassword!", email);
            if (!Roles.RoleExists(role))
            {
                Roles.CreateRole(role);
            }
            Roles.AddUserToRole(email, role);

Run the project. The aspnetdb.mdf database file will be created in App_Data, with the needed tables.

Delete the code added above.

Wednesday, October 12, 2016

Windows 10 Complaint #1: Auto Update State Loss

I wouldn’t care that Windows 10 restarts my computer after updates, if it would capture and restore my entire desktop state. That’s perfectly possible; I have hibernation enabled.

But I don’t like discovering my computer no longer has the twenty developer-related browser tabs open that took me two hours to find.

It feels like this.

Photo: Stephen Edmonds


EDIT 2016-10-12

I say “it’s perfectly possible,” but could be ignorant, know-it-all baloney on my part. I don’t know exactly how hibernate works. I suspect that it depends on several Windows OS files not being fully closed. In other words.

  1. The entire PC memory, including running processes, is written to disk.
  2. The PC can be powered off.
  3. Normally, on restart, there have been no changes to the Windows OS, so the processes can be resumed.
  4. But what if there are changes? What if an entire dll or exe has been removed? Then, trying to start that process could fail.

But….but!…can’t the application state be stored? Maybe not. These things often seem simple until you know what the hell you’re talking about.

Friday, September 9, 2016

Disable Windows 10 Photo Automatic Albums

image

It’s dumb that:

  1. Windows 10’s default photo viewing app automatically creates albums for you.
    image
  2. You can’t disable that feature.
  3. Instead, you have to remove the application using PowerShell.
  4. Which means your default photo viewing app becomes something dumb like Paint.

image

http://answers.microsoft.com/en-us/windows/forum/apps_windows_10-photos/is-there-any-way-to-disable-the-windows-10-photo/ce616a54-7ce0-44e3-8d47-d56589fc3743?page=1

PowerShell command to remove Photos:

Get-AppxPackage *photo* | Remove-AppxPackage

Note: According to some, setting another program (like Paint) as your default photo viewer might disable automatic album generation without removing the app. I didn’t test it, because the only thing I’d use the app for is as a viewer. Not an editor. Just an on-the-fly viewer.

------------ EDIT 1 -------------

It’s possible to restore using the Windows 7 Windows Photo Viewer as the default. The program is still installed in Windows 10, it just doesn’t have its file associations enabled by default. Follow these instructions:

http://www.tenforums.com/tutorials/14312-windows-photo-viewer-restore-windows-10-a.html

Note: I haven’t tried the above, but TenForums (and its sister, SevenForums) is reputable.

------------ EDIT 2 -------------

I’ve installed the free (for home use) FastStone Image Viewer, set it as as my default photo viewer, and changed one setting. I’m now happy. I can already see this app will make me more productive, and I’ll likely be donating money to it.

Setting I Changed

The default behavior of FastStone is to open a double-clicked image file in full screen mode. I prefer opening in a window because I often need to view the photos while doing something else.

  1. Open FastStone
  2. Settings (F12) > Viewer
  3. Associated image launches in: Windowed View
    image

Features

In full screen mode, moving the mouse to the top, bottom, right or left of the screen reveals a specific menu. For instance, at the top is thumbnails and some command buttons.

FastStone has a lot of features, but here are my needs and how FastStone met them.

Double-click an image and view in window.

  1. Search > Default Programs
  2. For Photo viewer, choose FastStone.

image

Easily move to next/previous image.

    • In any view, use the arrows to navigate.
    • In windowed view, there are buttons in the tool bar.
    • In any view, bring the mouse toward the screen bottom and arrows will appear/

image

Quickly get some image properties.

    • In any view, press “I”.
      image
    • In full screen view, move cursor to right side.

View as a slide show.

    • In windowed view, click the Slide Show button image
    • In full screen, move mouse to top, bottom or left and find the Slide Show option in the menu.

image

References

Here are 4 Best Image Viewers for Windows 10

Monday, September 5, 2016

A Layman’s Explanation of Mocking and Dependency Injection

A Sad Tale of Woe Again

image

So your husband or wife is a software engineer, and you’re not. You like the idea of software, you even use software, but you are as interested in what goes into creating software as you are in soap manufacturing. He (or she, but programming is still a stupidly male-dominated field, so we’ll stick with the percentages) comes home, blathering on about his day. The conversation goes something like this:

Him: “They handed me a legacy codebase today. It’s ancient .Net 2 stuff. I’m supposed to refactor the existing code and, in parallel, rewrite it to .Net 4.5.”

You: (silent, but thinking, “I wonder if crocodiles attack alligators. Or can they mate with them? You only hear about crocodiles or alligators, not crocodiles and alligators. Is a ‘crocogator’ a thing?”)

Him: “I spent about five hours just looking at the stack. What a mess! I mean, it’s not bad, really, but before I make any changes I need a way to unit test, and it’s not architected for that. I don’t want to go down the rabbit hole since I’m rewriting the whole thing using SOLID DDD principles, but I’ve got to get some DI going, and I’m going to have to figure out how to mock some of the internals.”

You: (nodding, and thinking, “If I pull weeds today, then I can mow tomorrow and feel virtuous two days in a row, and treat myself to wine at lunch on Saturday.”)

Him: “Can I brainstorm the unit testing with you? Just, you know, talk it out? That would really help.”

You: (nodding slowly, thinking, “O! M! G! Just cut off my head and pour cabbage into it! Still, he’s a good man. All I have to do is listen.”

Him: “Stop me any time if I can explain how something works.”

You: “OK, honey.” (but thinking, “The weeds. I was going to pull the weeds.”)

Unbaffling Language to the Rescue!

The only thing worse than listening to a software developer talk about code is asking a sailor about an upcoming voyage. Here are some actual nautical terms and phrases: cumshaw, geedunk, abeam, baggywrinkle, beat to quarters, by and large, coxswain. The definition of “death roll”?:  “In a keel boat, a death roll is the act of broaching to windward, putting the spinnaker pole into the water and causing a crash-gybe of the boom and mainsail, which sweep across the deck and plunge down into the water.” [Wikipedia]

Water. I drink water. I understand water.

Programmers don’t need to live lives of unending, habitual obfuscation. We can explain, if we but remember the lessons of literature.

The Totally Contrived, Ridiculous Metaphor

Imagine you’re a high school teacher. Now, imagine that you have a four-inch wood splinter going through your left eyelid. Which is easier on your mental state? If you say “splinter,” you must be a teacher.

Now, imagine a magical school where you don’t have to grade your own papers. You finish your eight-hour work day, go home, take an hour planning the next day’s lessons, have dinner, and study an hour or two for your required continuing education course, but you don’t have to grade at least twenty-five of the 120 five-page essays from mid-term exams.

Instead, you get to hand the exams to your Grading And Reports Department. It works like this:

  1. Give Mr Michael Murphy your stack of 120 essays.
  2. A few days later, pick up the graded essays and a formatted report of the students’ grades, broken down by class period, by student, and summarized with comparative aggregates. It’s a great report.

Recently, you were tasked with testing the GARD system. You’re a great choice, because you helped create the department. Here’s what you know:

  1. Mr Murphy takes the papers and gives them to Dr Marcia Malone. Dr Malone grades every paper. She gives the results back to Mr Murphy.
  2. Mr Murphy aggregates the grades and creates the formatted report.
  3. You helped train Dr Malone, who is brilliant. She can grade anything. But teachers have no control over how she grades.
  4. The grading scale Dr Malone uses could change at any time. Today, 90-100% could be an “A.” Tomorrow, 93-100% could be an “A.” (Remember, this is a contrived example.)

Here’s a lousy illustration.

You give the papers to Mr Murphy

image

Mr Murphy gives the papers to Dr Malone, who does mysterious, magical mischief.

image

Mr Murphy gives you back the papers.

image

You have only been asked to test the report formatting. This is critical! You are not verifying the grades are correct. You only care about the report. You devise this test

Given a stack of 120 papers, if the grades are abc, then report should look like xyz.

So here’s your challenge. You are going to give Mr Murphy 120 papers. He’s going to create the report. You’re going to compare what he gives you with how you know the report should look, right down to the numbers and letter grades on it. If they match, the test passes. If not, the test fails.

“Crap!” you think, “I can’t depend on Dr Malone to always give Mr Murphy the same grades! Besides, it takes her three days on average to grade that many papers, and I want my tests to be done in a day. It only takes Mr Murphy a few hours to prepare a report.”

You develop a plan. You are a genius.

  1. You build an automaton that looks like Dr Malone. But, it doesn’t actually grade anything. It just gives back a consistent set of scores that you tell it.
  2. When you give Mr Murphy the papers, you’ll also give him the automaton.
  3. Instead of Mr Murphy handing the papers to Dr Malone, he’ll hand them to the automaton and immediately get back your scores from it.
  4. Mr Murphy formats the report and gives it to you.

More laughable illustrations, but let’s include the programming terms.

We have a dependency on our grader, Dr Malone. We’ll change the GARD room so that we can give it a real or fake grader. This is called Dependency Injection.

image

Mr Murphy doesn’t care which grader he gets answers from. For our test, he uses the fake one. That is, he uses a Mock (also called a fake, or stub, or substitute).

image

We get back the report made from data we injected. We just want to compare the reports, the work Mr Murphy does.

image

If they match, the test passes. If not, fail!

image

How a programmer sees this

A programmer sees it the same way. Except it’s all words that look like English, but are alien-ese.

The Interface

image

The Production Code

image

Using the Production Code

image

The Test Code

image

Wrap Up

Dependency Injection and Mocking solve two problems that affect how well software can be tested.

  1. Dependency Injection lets us control what external dependencies, like a grading engine, a method uses. If we couldn’t do this, we’d have to always use production data, when that’s not what we’re always testing.
  2. Once we can inject a dependency, we can Mock its behavior. That is, we can make it do whatever we want, giving the method under test consistent results. Again, we’re not testing the dependent service. We’re testing the method that is using it.

It takes some work, but once you get your head wrapped around these concepts and their implementation, their importance becomes clear.