---
title: "Tips for Testable code and for testing legacy code"
url: "https://osherove.com/blog/2007/6/10/tips-for-testable-code-and-for-testing-legacy-code.md"
canonical: "https://osherove.com/blog/2007/6/10/tips-for-testable-code-and-for-testing-legacy-code.html"
published: "2007-06-10T13:09:28"
updated: "2007-06-10T13:09:28"
tags: ["Agile", "Agile Related", "Art Of Unit Testing", "Cool Tools", "Unit Testing"]
author: "Roy Osherove"
description: "I was consulting for a project today, and I was helping the team figure out how to test a method inside their business logic. Here's the thing - it was one of the least testable method's I've seen. It took me about 4 -5…"
usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)."
license: "https://creativecommons.org/licenses/by/4.0/"
---

# Tips for Testable code and for testing legacy code

By Roy Osherove June 10, 2007 In [Agile](https://osherove.com/blog/category/agile), [Agile Related](https://osherove.com/blog/category/agile-related), [Art Of Unit Testing](https://osherove.com/blog/category/art-of-unit-testing), [Cool Tools](https://osherove.com/blog/category/cool-tools), [Unit Testing](https://osherove.com/blog/category/unit-testing)

**Historical article** · Originally published June 10, 2007; technical details may be outdated.

I was consulting for a project today, and I was helping the team figure out how to test a method inside their business logic. Here's the thing - it was one of the least testable method's I've seen. It took me about 4 -5 hours to refactor the code to make it testable,and in the end it pretty much looked horrible.

We tested and and saw all the tests pass, but the feeling wasn't very good. This was legacy code at its most glorified being. Hard to test, hard to follow, and lots of dependencies sprinkled around.

I ended up make a couple of methods static on the class, make them take lots of parameters and send in lots of stubs (we used Rhino.Mocks). It worked, but we all felt kinda dirty in the end.

The thing that really kept coming up in my thoughts (and words) was how [TypeMock](http://www.typemock.com/) could have easily solved the problems in this scenario.  It would have taken less than 15 minutes to figure out how to test that thing with TypeMock. And yes, I wholeheartedly agree that using a powerfull such as TypeMock can help you 'forget' to do proper design, but in the end its about using the right tool for the right job.

For messy legacy situations, TypeMock will beat out any other mocking framework I know hands down because it allows  simply to mess around with the internals of a system without changing its code base. That's a powerful thing for legacy scenarios, and as such it is a perfect fit. I'll be going there next week and plan on showing them some of this tool's wonders.

Still, some interesting thoughts about what they can do next when they write the code, to make sure it's more testable:

- **Don't inherit from classes you can't control. Encapsulate and wrap it up**. They inherited from a lot of ESRI stuff and it was impossible to instantiate many of the classes involved because the constructors kept on taking problematic dependencies to be created. Had they wrapped the dependencies instead of derive from them, it would be much easier to use ["Extract & Override"](http://weblogs.asp.net/rosherove/articles/DependencyIssues.aspx) on the code to make it testable.
- **Make methods virtual by default**. The Java way. That makes it easy for tools such as Rhino.Mocks to create stubs and mocks from your real classes and override those virtual methods easily (making it much more easily testable because you can override any method that does something problematic like talk to a web service).
- **Don't use 'Sealed' unless you really have to**. And then _still_ don't use it unless it's a security issue. Sealed means you can't inherit from that class, and that leads to ugly stuff like I did today.
- **Make Singletons Testable**.

- **Add a setter** to the singleton instance, or make the factory that creates it configurable to create your own instance.
- Make sure a singleton **always return an interface** rather than a concrete class. It's easier to stub or mock an interface than to do the same with a class you'll need to inherit from.  It also creates less complications down the road.

- **Use _internal_ keyword** and the \[assembly:internalsVisibleTo()\] attribute to hide those setters from production code, but still make them visible to test code.
- If possible, **create an interface per class**. You never know when you're gonna need it.
- If possible, **write the code in a test driven manner**. That's the best way to ensure code coverage,having real tests for the code and having the code testable by default.
- Read [this article about design for testability](http://weblogs.asp.net/rosherove/articles/Design4Tesatbility1.aspx)

**Some general testing tips:**

- In [Rhino.Mocks](http://www.ayende.com/projects/rhino-mocks.aspx), using MockRepository.Stub<IMyInterface>() cane create an object that can have its properties be set and get freely on it, with no extra line of code. [More on this here](http://ayende.com/Wiki/\(S\(rak01h45dgeosu45hlg5f345\)\)/Default.aspx?Page=Rhino%20Mocks%20-%20Stubs).
- [TypeMock](http://www.typemock.com/) is a lifesaver when it comes to Legacy code.
- Writing interaction tests (using mocks and stubs) will help you (force you) know the code your testing intimately. Sometimes a little too much, actually.
- If you're planning to test the web UI, have a look at [Selenium](http://www.google.com/search?q=selenium+testing), [Fit](http://www.google.com/search?q=Fitnesse+Testing) and [Watin](http://www.google.com/search?hl=iw&q=Watin+testing&lr=)
- If you're planning to test database related code, [look here](http://weblogs.asp.net/rosherove/articles/dbunittesting.aspx).
- Some jobs are better left for the QA Department, such as visual testing (that something is drawn correctly for example), load testing, and sometimes data driven inputs for tests.

## More in Agile

[All posts in Agile](https://osherove.com/blog/category/agile)

- Jun 19, 2007

    ### [Art Of Unit Testing Book Available Shortly](https://osherove.com/blog/2007/6/19/art-of-unit-testing-book-available-shortly.html)

- Jun 13, 2007

    ### [Microsoft eScrum Version 1.0?](https://osherove.com/blog/2007/6/13/microsoft-escrum-version-10.html)

- Jun 7, 2007

    ### [List of Unit Testing Frameworks](https://osherove.com/blog/2007/6/7/list-of-unit-testing-frameworks.html)

- Jun 7, 2007

    ### [Chapter 5 - Mock Object Frameworks - Done](https://osherove.com/blog/2007/6/7/chapter-5-mock-object-frameworks-done.html)


---

## About the author

**Roy Osherove**: Senior Solutions Architect at AWS working on AI for production and AI-driven development; author of The Art of Unit Testing and Elastic Leadership, with about 20 years of consulting and training on unit testing, TDD, team leadership and continuous delivery.

### Sites

- [RobotPaper](https://robotpaper.ai/): This blog: AI patterns and anti-patterns, AI and coding agents, and engineering leadership.
- [osherove.com](https://osherove.com): Roy's personal site. Author of The Art of Unit Testing and Elastic Leadership; consulting and training on unit testing, TDD, team leadership and continuous delivery, plus about 20 years of blog posts.
- [The Art of Unit Testing](https://www.artofunittesting.com): The Art of Unit Testing, 3rd Edition (Manning): readable, maintainable, trustworthy unit tests, plus TDD workshops in C#, JavaScript, Java and Kotlin.
- [5whys.com](https://www.5whys.com): Roy's writing on software team leadership: self-organizing teams, surviving chaos, learning mode and the Elastic Leadership model.
- [Pipeline Driven](https://pipelinedriven.org): Continuous delivery and DevOps practices: build patterns, pipeline-friendly testing, DevOps metrics and enterprise DevOps.
- [Elastic Leadership](https://www.elasticleadership.com): Elastic Leadership, Roy's framework for software team leaders (survival, learning and self-organizing modes).

### Social

- X: https://x.com/royosherove
- LinkedIn: https://www.linkedin.com/in/osherove/

### Contact

- Contact form: https://forms.gle/jQSx5KoXvrVA1JCK7

### License

Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page). License: https://creativecommons.org/licenses/by/4.0/
