I recently joined a company where they use TDD, but it's still not clear for me, for example, we have a test:
[TestMethod]
public void ShouldReturnGameIsRunning()
{
var game = new Mock<IGame>();
game.Setup(g => g.IsRunning).Returns(true);
Assert.IsTrue(game.Object.IsRunning);
}
What's the purpose of it? As far as I understand, this is testing nothing! I say that because it's mocking an interface, and saying, return true for IsRunning, it will never return a different value...
I'm probably thinking wrong, as everybody says it's a good practice etc etc... or is this test wrong?
This test is excerising an interface, and verifying that the interface exposes a Boolean getter named IsRunning.
This test was probably written before the interface existed, and probably well before any concrete classes of IGame existed either. I would imagine, if the project is of any maturity, there are other tests that exercise the actual implementions and verify behavior for that level, and probably use mocking in the more traditional isolationist context rather than stubbing theoretical shapes.
The value of these kinds of tests is that it forces one to think about how a shape or object is going to be used. Something along the lines of "I don't know exactly what a game is going to do yet, but I do know that I'm going to want to check if it's running...". So this style of testing is more to drive design decisions, as well as validate behavior.
Not the most valuable test on the planet, but serves its purpose in my opinion.
Edit: I was on the train last night when I was typing this, but I wanted to address Andrew Whitaker comment directly in the answer.
One could argue that the signature in the interface itself is enough of an enforcement of the desired contract. However, this really depends on how you treat your interfaces and ultimately how you validate the system that you are trying to test.
There may be tangible value in explicitly stating this functionality as a test. You are explicitly verifying that this is a desired functionality for an IGame.
Lets take a use case, lets say that as a designer you know that you want to expose a public getter for IsRunning, so you add it to the interface. But lets say that another developer gets this and sees a property, but doesn't see any usages of it anywhere else in the code, one might assume that it is eligible for deletion (or code-rot removal, which is normally a good thing) without harm. The existence of this test, however, explicitly states this properity should exist.
Without this test, a developer could modify the interface, drop the implementation and the project would still compile and run seemingly correctly. And it would be until much later that someone might notice that interface has been changed.
With this test, even if it appears as if no one is using it, your test suite will fail. The self documenting nature of the test tells you that ShouldReturnGameIsRunning(), which at the very least should spawn a conversation if IGame should really expose an IsRunning getter.
The test is invalid. Moq is a framework used to "mock" objects used by the method under test. If you were testing IsRunning, you might use Mock to provide a certain implementation for those methods that IsRunning depends on, for example to cause certain execution paths to execute.
People can tell you all day that testing first is better; you won't realize that it actually is until you start doing it yourself and realize that you have fewer bugs with code you wrote tests for first, which will save you and your co-workers time and probably make the quality of your code higher.
It could be that the test has been written (before) the code which is good practice.
It might equally be that this is a pointless test created by a tool.
Another possibility is that the code was written by somebody who, at the time, didn't understand how to use that particular mocking framework - and wrote one or more simple tests to learn. Kent Beck talked about that sort of "learning test" in his original TDD book.
This test could have had a point in the past. It could have been testing a concrete class. It could have been testing an abstract one -- as it sometimes makes sense to mock an abstract class that you want to test. I can see how a (less informed(like myself)) follower of the TDD way of doing things could have left a small mess like this. Cleanup of dead code and dead test code, does not really fit in the natural workflow of red, green, refactor (since it doesn't break any tests!).
However, history is not justification for a test that does nothing but confuse the reader. So, be a good boyscout and remove it.
In my honest oppinion this is just rubbish, it only proves that moq works as expected
Related
I'm writing unit tests for the implementation of an API I wrote myself in my company's application. Still new to this whole thing. When looking for answeres on how to unit test certain things I come across a certain pattern. It goes something like this:
Question:
I have this private method I need to unit test.
Top voted answer:
Don't.
I also came across this article arguing against unit testing private methods as well.
Basically how I'm implementing an API I'm given is I write the code first, then I write unit tests to "break it the worst way possible" (as my superior puts it). Once I notice something broke I fix it in the code. To me this seems like a mash-up of OOD and TDD. Is that a legit approach?
The reason I got so many private methods in the first place is that I'm required to break up larger chunks of code into methods. Since these methods are only supposed to be used within the scope of this API implementation I set them to private. Since the file structure established by my team requires me to write all the code into a single file corresponding to an API I can't separate these private methods into a new class and set them to public.
My superior expects me to test these private methods as well. But I'm beginning to doubt if this is even really necessary if the Asserts on the public methods all run successfully?
From my point of view, if my tests on the public methods return the values I expected, I infer that my private methods also work like I intended.
Or am I missing something?
The core point is: unit tests exist to guarantee that your class under tests behaves as expected.
The behavior of your classes manifests itself via those methods that can be called from "outside" of your classes.
Therefore there is neither need nor sense in trying to directly test private methods.
Of course, it is fair to measure coverage while running unit tests; in order to understand which paths in your code are taken. This information can be used to either enhance test cases (to gain more coverage); or to delete production code (which isn't required).
And to align with your question: you do not use TDD to implement private methods.
You use TDD to create a special form of your "contract" that can be executed automatically. You verify what needs to be done; not how it is actually done in detail. That is especially true since the TDD methodology includes continuous refactoring. You write your tests, you turn them green (by writing production code); and then, at some point, you look into improving the quality of your code. Meaning: you start reworking internal aspects of your class under test. Like: creating more private methods, moving content around; maybe even creating internal-only helper classes and so on. But you keep running your existing tests ... which should still all work; because as said: you write them to check the externally observable behavior (as far as possible).
And beyond that: you should rather looking into "fuzzying" the test data that your unit tests drive into your code instead of worrying about private methods.
What I mean: instead of trying to manually find that test data that makes your production code break, look into concepts like QuickCheck that try to do exactly that automatically.
Final words: and if your management keeps hammering on "test private methods"; then it is your responsibility as engineer to convince them that they are wrong about this. And there is plenty of material out there to back that up.
The way you are splitting your code at the moment is out of necessity. You are delegating some work in a private method, because, well, other public methods need to re-use this, and you don't want to copy-paste that code. Of course, since these methods don't make sense being used as standalone methods, you keep them private.
Good, at least you're true to the DRY (Don't Repeat Yourself) principle.
Now, another way to look it is that you want to separate your private methods from the rest of the code, because you want to have a Separation of Concerns. If you do this, you will see that these private methods, although they can't be used on their own, don't really belong to the class containing your public methods, because they don't solve the same concern : This is the Single Responsibility principle: the S in SOLID.
Instead of having your private method within your class, what you can do is move it to another class (a service as I call them), inject it in the class in which they were before, and call these methods instead of the call to the private ones.
Why should you do this ?
Because it will be so much easier to test: you delegate a big part of the code, that you will not have to test under a big combination of scenarios.
Because you can then inject an alternative implementation (think maintainability: it's easier to replace a brick, than a part of a brick)
Because you can delegate the implementation (and the testing) of this service to someone else (you can have 2 developers in parallel working on a very small area of the code)
Sometimes, it makes even more sense, because these service classes will then be re-used by other completely different classes that will have the same needs, if they really take care of one single concern.
This last point doesn't always happen, but quite often, it does. I found it is easier to re-use existing data services when they are self-documented: properly-named services and properly-named methods. (your co-workers will discover them more easily)
Now, you don't need to test a private method... because it's public.
You may think it's cheating, because you just made it public, but this comes from a very legitimate approach: Separation of Concerns.
Final notes:
I am convinced your superior is right about asking you to test this code. One thing he could have added was to do that separation into different classes. Also, make sure that you inject these classes using Dependency Injection and Inversion of Control containers. don't instantiate them using the new statement, otherwise, you will not be able to assert that the right method was called with the right arguments !
I've been reading up on Mocks and Stubs, their differences and uses. I'm still a bit confused, but I think I've got the jist of it.
Now I'm wondering about applications. I can see the use in creating "fake" objects in testing scenarios where the actual objects are too complicated to haul around to test one aspect.
But let's consider my application: I'm working on a computational geometry library. Our library defines points, lines, linesegments, vectors, polygons, and polyhedra, along with a bunch of other objects and all the usual geometric operations. Any given object is stored as a list of points or directions, or lower level objects. But none of these objects takes more than a few milliseconds to generate.
When I'm testing this library, does it make sense to use Mocks/Stubs anywhere?
Right now we just use particular test cases. We're calling them stubs, but I don't think they meet the technical definition of a stub. What do you think better vocab for that would be? "TestCases"? "Examples"?
SourceCode: https://bitbucket.org/Clearspan/geometry-class-library/src
Edit: Note that we're striving for immutability in all our geometry objects, so it only makes sense to test the results of operations, but not state changes to the initial objects.
The fundamental difference between mock and stub is that mock can make your test fail. Stub can't. Stub is used to guarantee correct program flow. It is never part of assert.
Note that mock can also be used to guarantee flow. In other words, every mock is also a stub, and stub is never a mock. Because of such overlapping responsibilities nowadays you don't see much distinction between mock and stub and framework designers go for more general terms (like fake, substitute or catch-all mock).
This realization (mock - assert, stub - flow) helps us narrow down some usage scenarios. To start with the easier one...
Mock
As I mentioned mocks are used in asserts. When the expected behavior of your component is that it should talk to this other component - use mock. All those
emailSender.SendEmail(email);
endOfDayRunner.Run();
jobScheduler.ScheduleJob(jobDetails);
can be only tested by asking "Did it call ScheduleJob with such and such parameters?" This is where you go for mock. Usually this will be mock's only usage scenario.
Stub
With stub it's a bit different. Whether to use stub or not is a design question. Once you follow regular loosely coupled, dependency injection-based design, eventually you will end up with a lot of interfaces.
Now, when in test, how do return value from interface? You either stub it or use real implementation. Each approach has its pros and cons:
with library-generated stubs, your tests will be less brittle but might require more up-front work (setting up stub and such)
with real implementations, setup work is already done but when Angle class changes CoordinateSystem might fail... Is such behavior desirable or not?
Is it? Which one to use? Both! It all depends on...
Unit of work
We arrived at final and the actual part of the problem. What is the scope of your unit test? What is the unit? Can CoordinateSystem be detached from its inner workings and dependencies (Angle, Point, Line) and can they be stubbed? Or more importantly, should they be?
You always need to identify what your unit is. Is it CoordinateSystem alone or perhaps Angle, Line and Point play important part of it? In many, many cases, the unit will be formed by both method and its surrounding ecosystem, including domain objects, helper classes, extensions or sometimes even other methods and other classes.
Naturally, you can separate them and stub all the way around but then... is it really your unit?
As a rule of thumb, use Mocks when you need to simulate behavior, and stubs when the only thing that matters in your test is the state of the object you're communicating with.
Taking into consideration the edit you made to your post, when you need to receive an immutable object use a stub, but when you need to call operations that object exposes then go for a mock, this way you are not prone to failing tests due to errors in another class implementation.
Should you Unit Test simple properties of a class, asserting that a value is set and retrieved? Or is that really just unit testing the language?
Example
public string ConnectionString { get; set; }
Test
public void TestConnectionString()
{
var c = new MyClass();
c.ConnectionString = "value";
Assert.Equal(c.ConnectionString, "value");
}
I guess I don't see the value in that.
I would suggest that you absolutely should.
What is an auto-property today may end up having a backing field put against it tomorrow, and not by you...
The argument that "you're just testing the compiler or the framework" is a bit of a strawman imho; what you're doing when you test an auto-property is, from the perspective of the caller, testing the public "interface" of your class. The caller has no idea if this is an auto property with a framework-generated backing store, or if there is a million lines of complex code in the getter/setter. Therefore the caller is testing the contract implied by the property - that if you put X into the box, you can get X back later on.
Therefore it behooves us to include a test since we are testing the behaviour of our own code and not the behaviour of the compiler.
A test like this takes maybe a minute to write, so it's not exactly burdensome; and you can easily enough create a T4 template that will auto-generate these tests for you with a bit of reflection. I'm actually working on such a tool at the moment to save our team some drudgery
If you're doing pure TDD then it forces you to stop for a moment and consider if having an auto public property is even the best thing to do (hint: it's often not!)
Wouldn't you rather have an up-front regression test so that when the FNG does something like this:
//24-SEP-2013::FNG - put backing field for ConnectionString as we're now doing constructor injection of it
public string ConnectionString
{
{get { return _connectionString; } }
{set {_connectionString="foo"; } }//FNG: I'll change this later on, I'm in a hurry
}
///snip
public MyDBClass(string connectionString)
{
ConnectionString=connectionString;
}
You instantly know that they broke something?
If the above seems contrived for a simple string property I have personally seen a situation where an auto-property was refactored by someone who thought they were being oh so clever and wanted to change it from an instance member to a wrapper around a static class member (representing a database connection as it happens, the resons for the change are not important).
Of course that same very clever person completely forgot to tell anyone else that they needed to call a magic function to initialise this static member.
This caused the application to compile and ship to a customer whereupon it promptly failed. Not a huge deal, but it cost several hours of support's time==money....
That muppet was me, by the way!
EDIT: as per various conversations on this thread, I wanted to point out that a test for a read-write property is ridiculously simple:
[TestMethod]
public void PropertyFoo_StoresCorrectly()
{
var sut = new MyClass();
sut.Foo = "hello";
Assert.AreEqual("hello", sut.Foo, "Oops...");
}
edit: And you can even do it in one line as per Mark Seeman's Autofixture
I would submit that if you find you have such a large number of public properties as to make writing 3 lines like the above a chore for each one, then you should be questioning your design; If you rely on another test to indicate a problem with this property then either
The test is actually testing this property, or
You will spend more time verifying that this other test is failing because the property is incorrect (via debugger, etc) than you would have spent typing in the above code
If some other test allows you to instantly tell that the property is at fault, it's not a unit test!
edit (again!): As pointed out in the comments, and rightly so, things like generated DTO models and the like are probably exceptions to the above because they are just dumb old buckets for shifting data somewhere else, plus since a tool created them, it's generally pointless to test them.
/EDIT
Ultimately "It depends" is probably the real answer, with the caveat that the best "default" disposition to be the "always do it" approach, with exceptions to that taken on an informed, case by case basis.
Generally, no. A unit test should be used to test for the functionality of a unit. You should unit test methods on a class, not individual, automatic properties (unless you are overriding the getter or setter with custom behaviour).
You know that assigning a string value to an automatic string property will work if you get the syntax and setter value correct as that is a part of the language specification. If you do not do this then you will get a runtime error to point out your flaw.
Unit tests should be designed to test for logical errors in code rather than something the compiler would catch anyway.
EDIT: As per my conversation with the author of the accepted answer for this question I would like to add the following.
I can appreciate that TDD purists would say you need to test automatic properties. But, as a business applications developer I need to weigh up, reasonably the amount of time I could spend writing and performing tests for 'trivial' code such as automatic properties compared to how long it would reasonably take to fix an issue that could arise from not testing. In personal experience most bugs that arise from changing trivial code are trivial to fix 99% of the time. For that reason I would say the positives of only unit testing non-language specification functionality outweigh the negatives.
If you work in a fast paced, business environment which uses a TDD approach then part of the workflow for that team should be to only test code that needs testing, basically any custom code. Should someone go into your class and change the behavior of an automatic property, it is their responsibility to set up a unit test for it at that point.
I would have to say no. If that doesn't work, you have bigger problems. I know I don't. Now some will argue that having the code alone would make sure the test failed if the property was removed, for example. But I'd put money on the fact that if the property were removed, the unit test code would get removed in the refactor, so it wouldn't matter.
Are you adhering to strict TDD practices or not?
If yes then you absolutely should write tests on public getters and setters, otherwise how will you know if you've implemented them correctly?
If no, you still probably should write the tests. Though the implementation is trivial today, it is not guaranteed to remain so, and without a test covering the functionality of a simple get/set operation, when a future change to implementation breaks an invariant of "setting property Foo with a value Bar results in the getter for property Foo returning value Bar" the unit tests will continue to pass. The test itself is also trivially implemented, yet guards against future change.
The way I see is that how much unit testing (or testing in general) is down to how confident are you that the code works as designed and what are the chances of it breaking in the future.
If you have a lower confidence of the code breaking (maybe due to the code being out sourced and the cost of checking line by line is high) then perhaps unit testing properties is appropriate.
Once thing you can do is write a helper class that can go over all get/set properties of a class to test that they still behave as designed.
Unless the properties perform any other sort of logic, then no.
Yes, it is like unit testing the language. It would be completely pointless to test simple auto-implemented properties otherwise.
According to the book The Art of Unit Testing With Examples in .NET, a unit test covers not any type of code, it focuses on logical code. So, what is logical code?
Logical code is any piece of code that has some sort of logic in it, small as it may be. It’s logical code if it has one or more of the
following: an IF statement, a loop, switch or case statements,
calculations, or any other type of decision-making code.
Does a simple getter/setter wrap an any logic? The answer is:
Properties (getters/setters in Java) are good examples of code that
usually doesn’t contain any logic, and so doesn’t require testing. But
watch out: once you add any check inside the property, you’ll want to
make sure that logic is being tested.
My answer which is from former test manager viewpoint and currently a development manager ( responsible for software delivery in time and quality) viewpoint. I see people are mentioning pragmatism. Pragmatism is not a good adviser because it may pair up with laziness and/or time pressure. It may led you on the wrong way. If you mention pragmatism you have to be careful to keep your intentions on the track of professionalism and common sense. It requires humility to accept the answers because they might not that you want to hear.
From my viewpoint what is important are the next:
you should find the defect as early as possible. Doing so you have to apply proper testing strategy. If it is testing properties then you have to test properties. If not, then don't do it. Both comes with a price.
your testing should be easy and fast. The bigger part (unit, integration, etc.) of the code tested in build time is the better.
you should do root cause analysis to answer the questions below and make your organization protected from the current type of error. Don't worry, another type of defect will come up and there will be always lessons to be learned.
what the root cause is?
how to avoid it next time?
another aspect is the cost of creating/maintaining tests. Not testing properties because they are boring to maintain and/or you have hundreds of properties is ridiculous. You should create/apply tools which makes the woodcutting job instead of human. In general, you always have to enhance your environment in order to be more efficient.
what other says are not good adviser - doesn't matter whether it was said by Martin Fowler or Seeman - the environment they are I'm pretty sure not the same as you are in. You have to use your knowledge and experience to setup what is good for your project and how to make it better. If you apply things because they were said by people you are respect without even thinking it through you will find yourself in deep trouble. I do not say that you don't need advises and/or other people help or opinion, you have to apply common sense to apply them.
TDD does not answer two important question, however, BDD does give you answers for the questions below. But, if you follow only one, you won't have delivery in time and quality. So doesn't matter whether you are purist TDD guy or not.
what must be tested? ( it says everything must be tested - wrong answer in my opinion )
when testing must be finished?
All in all, there is no good answer. Just other questions you have to answer to get that temporary point where you are able to decide whether it is needed or not.
There are some other variations of this question here at SO, but please read the entire question.
By just using fakes, we look at the constructor to see what kind of dependencies that a class have and then create fakes for them accordingly.
Then we write a test for a method by just looking at it's contract (method signature). If we can't figure out how to test the method by doing so, shouldn't we rather try to refactor the method (most likely break it up in smaller pieces) than to look inside it to figure our how we should test it? In other words, it also gives us a quality control by doing so.
Isn't mocks a bad thing since they require us to look inside the method that we are going to test? And therefore skip the whole "look at the signature as a critic".
Update to answer the comment
Say a stub then (just a dummy class providing the requested objects).
A framework like Moq makes sure that Method A gets called with the arguments X and Y. And to be able to setup those checks, one needs to look inside the tested method.
Isn't the important thing (the method contract) forgotten when setting up all those checks, as the focus is shifted from the method signature/contract to look inside the method and create the checks.
Isn't it better to try to test the method by just looking at the contract? After all, when we use the method we'll just look at the contract when using it. So it's quite important the it's contract is easy to follow and understand.
This is a bit of a grey area and I think that there is some overlap. On the whole I would say using mock objects is preferred by me.
I guess some of it depends on how you go about testing code - test or code first?
If you follow a test driven design plan with objects implementing interfaces then you effectively produce a mock object as you go.
Each test treats the tested object / method as a black box.
It focuses you onto writing simpler method code in that you know what answer you want.
But above all else it allows you to have runtime code that uses mock objects for unwritten areas of the code.
On the macro level it also allows for major areas of the code to be switched at runtime to use mock objects e.g. a mock data access layer rather than one with actual database access.
Fakes are just stupid dummy objects. Mocks enable you to verify that the controlflow of the unit is correct (e.g. that it calls the correct functions with the expected arguments). Doing so is very often a good way to test things. An example is that a saveProject()-function probably want's to call something like saveToProject() on the objects to be saved. I consider doing this a lot better than saving the project to a temporary buffer, then loading it to verify that everything was fine (this tests more than it should - it also verifies that the saveToProject() implementation(s) are correct).
As of mocks vs stubs, I usually (not always) find that mocks provide clearer tests and (optionally) more fine-grained control over the expectations. Mocks can be too powerful though, allowing you to test an implementation to the level that changing implementation under test leaving the result unchanged, but the test failing.
By just looking on method/function signature you can test only the output, providing some input (stubs that are only able to feed you with needed data). While this is ok in some cases, sometimes you do need to test what's happening inside that method, you need to test whether it behaves correctly.
string readDoc(name, fileManager) { return fileManager.Read(name).ToString() }
You can directly test returned value here, so stub works just fine.
void saveDoc(doc, fileManager) { fileManager.Save(doc) }
here you would much rather like to test, whether method Save got called with proper arguments (doc). The doc content is not changing, the fileManager is not outputting anything. This is because the method that is tested depends on some other functionality provided by the interface. And, the interface is the contract, so you not only want to test whether your method gives correct results. You also test whether it uses provided contract in correct way.
I see it a little different. Let me explain my view:
I use a mocking framework. When I try to test a class, to ensure it will work as intended, I have to test all the situations may happening. When my class under test uses other classes, I have to ensure in certain test situation that a special exceptions is raised by a used class or a certain return value, and so on... This is hardly to simulate with the real implementations of those classes, so I have to write fakes of them. But I think that in the case I use fakes, tests are not so easy to understand. In my tests I use MOQ-Framework and have the setup for the mocks in my test method. In case I have to analyse my testmethod, I can easy see how the mocks are configured and have not to switch to the coding of the fakes to understand the test.
Hope that helps you finding your answer ...
Many times I find myself torn between making a method private to prevent someone from calling it in a context that doesn't make sense (or would screw up the internal state of the object involved), or making the method public (or typically internal) in order to expose it to the unit test assembly. I was just wondering what the Stack Overflow community thought of this dilemma?
So I guess the question truly is, is it better to focus on testability or on maintaining proper encapsulation?
Lately I've been leaning towards testability, as most of the code is only going to be leveraged by a small group of developers, but I thought I would see what everyone else thought?
Its NOT ok to change method visibility on methods that the customers or users can see. Doing this is ugly, a hack, exposes methods that any dumb user could try to use and explode your app... its a liability you do not need.
You are using C# yes? Check out the internals visible to attribute class.
You can declare your testable methods as internal, and allow your unit testing assembly access to your internals.
It depends on whether the method is part of a public API or not. If a method does not belong to part of a public API, but is called publicly from other types within the same assembly, use internal, friend your unit test assembly, and unit test it.
However, if the method is not/should not be part of a public API, and it is not called by other types internal to the assembly, DO NOT test it directly. It should be protected or private, and it should only be tested indirectly by unit testing your public API. If you write unit tests for non-public (or what should be non-public) members of your types, you are binding test code to internal implementation details.
Thats a bad kind of coupling, increases the amount of unit tests you need, increases workload both in the short term (more unit tests) as well as in the long term (more test maintenance and modification in response to refactoring internal implementation details). Another problem with testing non-public members is that you test code that may not actually be needed or used. A GREAT way to find dead code is when it is not covered by any of your unit tests when your public API is covered 100%. Removing dead code is a great way to keep your code base lean and mean, and is impossible if you are not careful about what you put into your public API, and what parts of your code you unit test.
EDIT:
As a quick additional note...with a properly designed public API, you can very effectively use a tool like Microsoft PEX to automatically generate full-coverage unit tests that test every execution path of your code. Combined with a few manually written tests that cover critical behavior, anything not covered can be considered dead code and removed, and you can greatly shortcut your unit testing process.
This is a common thought.
It's generally best to test the private methods by testing the public methods that call them (so you don't explicitly test the private methods). However, I understand that there are times when you really do want to test those private methods.
The answers to this question (Java) and this question (.NET) should be helpful.
To answer the question: no, you shouldn't change method visibility for the sake of testing. You generally shouldn't be testing private methods, and when you do, there are better ways to do it.
In general I agree with #jrista. But, as usual, it depends.
When trying to work with legacy code, the key is to get it under test. After that, you can add tests for new features and existing bugs, refactor to improve design, etc. This is risky without tests. Legacy code tends to be rife with dependencies, and is often extremely difficult to get under test.
In Working Effectively with Legacy Code, Michael Feathers suggests multiple techniques for getting code under test. Many of these techniques involve breaking encapsulation or complicating the design, and the author is up front about this. Once tests are in place, the code can be improved safely.
So for legacy code, do what you have to do.
In .NET you should use Accessors for unit testing, even rather than the InternalsVisibleTo attribute. Accessors allow you to get access to any method in the class even if it is private. They even let you test abstract classes using an empty mock derived object (see the "PrivateObject" class).
Basically in your test project you use the accessor class rather than the actual class with the methods you want to test. The accessor class is the same as the "real" class, except everything is public to your test project. Visual studio can generate accessors for you.
NEVER make a type more visible to facilitate unit testing.
IMO is it WRONG to say that you should not unit test private methods. Unit tests are of exceptional value for regression testing and there is no reason why private methods should not be regression tested with granular unit tests.