Unit testing is a software development process in which the smallest testable parts of an application, called units, are individually and independently scrutinized for proper operation.

Unit testing is a lot like going to the gym. When you first start out it’s miserable, you question why you’re putting yourself through it but over time you start seeing the results and realize you should have been doing it all along.

I’ve gone through all those phases in my development career and I’ve now reached the point that I couldn’t imagine writing code and not writing unit tests and it’s no different when using Workflow.

First, let’s talk about a few of keys to writing a good unit test and how code activities play into that:

  1. Make each test independent.
    1. Tests should not rely on the result of any other test. Code activities and the visual nature of workflows help to point out where you may be trying to do too much in your code.
  2. Test only one code unit at a time.
    1. Code activities know nothing about other code activities. All data is passed using in and out arguments. While you can still overload your code activities with lots of logic, you should be able to “smell” the bad coding practice.
  3. Mock external dependencies.
    1. Workflow offers a fantastic service location pattern called “Workflow Extensions” (more to come in a future post on this topic).

Writing unit tests for code activities is almost identical to any other unit tests except in how you call the code. In our “Because” method we’re going to use the “WorkflowInvoker” to call the code activity and pass in our mocked up data through the arguments. We’ll use our Loan example from my earlier post to illustrate.

In our test init we will setup our base mock object.

public void TestInit()
{
_result = new bool?();

_loan = new Loan
{
LoanAmount = 100,
DownPaymentAmount = 20,
CreditRating = 700,
HasCollateral = true
};
}

Next, in our “Because” method we will wire up the call to the code activity.

private void Because()
{
//Create a new instance of our code activity
var validateLoanIsCompleteActivity = new WorkflowWebApiExample.CodeActivities.ValidateLoanIsComplete();
//Create a new WorkflowInvoker instance.
var workflowInvoker = new WorkflowInvoker(validateLoanIsCompleteActivity);
//Create a new input argument dictionary
var InputArguments = new Dictionary<string, object>();
//Add our argument to the dictionary.
InputArguments.Add("Loan", _loan);
//Invoke the workflow and capture the result.
var resultDictionary = workflowInvoker.Invoke(InputArguments);
//Cast the result to the appropriate type.
_result = (bool)resultDictionary["Valid"];
}

Finally, we write our test.

public void Should_return_false_for_valid_if_loan_amount_is_0()
{
_loan.LoanAmount = 0;

Because();

Assert.IsFalse(_result.Value, "Expected to receive false when the amount was 0 but _result was true.");
}

It’s just that simple. There’s no real reason to not write tests for your code activities.

You can see this test in action in a sample project available on GitHub.

Blake Helms

Blake Helms is a .NET Software Development Manager for EBSCO Industries, a global company with businesses in a range of industries including Information Services, Publishing and Digital Media, Outdoor Products, Real Estate, Manufacturing and Distribution, and Business Services, headquartered in Birmingham, Alabama. There he is responsible for several core business applications and has been a driver for software craftsmanship and creating a culture that promotes mentorship and continuous improvement. He is also the cofounder of the Birmingham .NET Meetup with a mission to promote good development practices and .NET technologies in the Birmingham, Alabama area. Blake is incredibly passionate about technology in all areas from writing code for work, to audio/video production for his church to automating his home.