No que diz respeito à definição comum de testes unitários, eu diria que não. Eu vi um código simples confuso devido à necessidade de torçá-lo para se adequar à estrutura de teste (por exemplo, interfaces e IoC em todos os lugares, tornando as coisas difíceis de seguir através de camadas de chamadas de interface e dados que devem ser óbvios transmitidos por magia). Dada a escolha entre o código que é fácil de entender ou o código que é fácil de testar na unidade, eu sempre uso o código de manutenção.
Isso não significa não testar, mas encaixar as ferramentas de acordo com você, e não o contrário. Existem outras maneiras de testar (mas código difícil de entender é sempre código incorreto). Por exemplo, você pode criar testes unitários menos granulares (por exemplo, a atitude de Martin Fowler de que uma unidade é geralmente classe, não um método), ou você pode acessar seu programa com testes de integração automatizados. Tal pode não ser tão bonito como o seu quadro de testes se acende com carrapatos verdes, mas estamos atrás do código testado, não da gamificação do processo, certo?
Você pode tornar seu código fácil de manter e ainda ser bom para testes de unidade, definindo boas interfaces entre eles e, em seguida, escrevendo testes que exercitam a interface pública do componente; ou você pode obter uma estrutura de teste melhor (uma que substitua as funções em tempo de execução para ridicularizá-las, em vez de exigir que o código seja compilado com mocks no lugar). Uma estrutura de teste de unidade melhor permite que você substitua a funcionalidade GetCurrentTime () do sistema com a sua própria, em tempo de execução, para que você não precise introduzir wrappers artificiais para isso apenas para se adequar à ferramenta de teste.