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:
- Make each test independent.
- 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.
- Test only one code unit at a time.
- 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.
- Mock external dependencies.
- 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.
//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;
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.