Occasionally, I’ll run across a case where some code (usually a background process) is looping, maintaining some kind of state, and checking for state change. For example, I have an application which monitors a file for changes. It does this by checking the file timestamp, and, if it has changed from the last run, operating on the file.
When I find this code, it is frequently a long loop with a bunch of code in between. Infinite loops are essentially impossible to test, so whenever you have a case like that, your first goal is to move as much code as possible outside of the loop. The best way I’ve found to do this is to separate the state management from the operation.
First, identify all the state variables within the method. One way to think about this is which variables will stop working if you were to reset them at the top of every loop. Take all of these variables and create a value object for them. Then take the rest of the code and move it to a new method which take the value object as an argument and returns one. Then change the loop to just call the method, passing the value object, and then assign the output to the same value object.
By doing this, the loop now has minimal code which can be visually audited. The rest of the state logic is now encapsulated inside of a method (which can be refactored easily into one or more command objects of needed) which is easy to test. You can now write tests which create a state situation, pass it into the method, and then examine the resulting state.