In this particular example, FunctionB can be public static but in a different class.
–
LeonidFeb 26 '13 at 19:27

For Code Review, you are expected to post actual code not a simplified version of it. See the FAQ. As its stands, you are asking a specific question not looking for a code review.
–
Winston EwertFeb 27 '13 at 16:28

1

FunctionB is broken-by-design. new Random().Next() is almost always wrong. You should inject the instance of Random. (Random is also a badly designed class, which can cause a few additional problems)
–
CodesInChaosFeb 27 '13 at 16:51

3 Answers
3

Disclaimer : not a C# programmer (mostly Java or Ruby). My answer would be : I would not test it at all, and I do not think you should.

The longer version is : private/protected methods are not parts of the API, they are basically implementation choices, that you can decide to review, update or throw away completely without any impact on the outside.

I suppose you have a test on FunctionA(), which is the part of the class that is visible from the external world. It should be the only one that has a contract to implement (and that could be tested). Your private/protected method has no contract to fulfil and/or test.

Following the comment, if FunctionB is public, I'll simply test both using unit test. You may think that the test of FunctionA is not totally "unit" (as it call FunctionB), but I would not be too worried by that : if FunctionB test works but not FunctionA test, it means clearly that the problem is not in the subdomain of FunctionB, which is good enough for me as a discriminator.

If you really want to be able to totally separate the two tests, I would use some kind of mocking technique to mock FunctionB when testing FunctionA (typically, return a fixed known correct value). I lack the C# ecosystem knowledge to advice a specific mocking library, but you may look at this question.

Completely agree with @Martin answer. When you write unit tests for class you should not test methods. What you're testing is a class behavior, that the contract (the declaration what class is supposed to do) is satisfied. So, your unit tests should cover all the requirements exposed for this class (using public methods/properties), including exceptional cases
–
almazFeb 26 '13 at 16:29

Hello, thanks for the response, but it didn't answer my question. I doesn't matter if FunctionB was private / protected. It can also be public and still be called from FunctionA.
–
tranceru1Feb 26 '13 at 16:32

The most common way to handle this problem, without redesigning the base class, is to subclass MyClass and override the method with the functionality you want to stub. It might also be a good idea to update your question to include that FunctionB could be public.
–
E-ManFeb 26 '13 at 16:50

1

protected methods are part of the public surface of a class, unless you ensure that there can be no implementations of your class in different assemblies.
–
CodesInChaosFeb 27 '13 at 17:07

2

The fact that FunctionA calls FunctionB is an irrelevant detail from a unit testing perspective. If the tests for FunctionA are written correctly, it is an implementation detail that could be refactored-out later without breaking tests (so long as the overall behavior of FunctionA is left unchanged). The real issue is that FunctionB's retrieval of a random number needs to be done with an injected object, so that you can use a mock during testing to ensure that a well-known number is returned. This allows you test well-known inputs/outputs.
–
Dan LyonsFeb 27 '13 at 18:27

I subscribe to the theory that if a function is important to test, or is important to replace, it is important enough to not be a private implementation detail of the class under test, but to be a public implementation detail of a different class.

So if I am in a scenario where I have

class A
{
public B C()
{
D();
}
private E D();
{
// i actually want to control what this produces when I test C()
// or this is important enough to test on its own
// and, typically, both of the above
}
}

Now I have a scenario where D() is independently testable, and fully replaceable.

As a means of organization, my collaborator might not live at the same namespace level. For example, if A is in FooCorp.BLL, then my collaborator might be another layer deep, as in FooCorp.BLL.Collaborators (or whatever name is appropriate). My collaborator might further only be visible inside the assembly via the internal access modifier, which I would then also expose to my unit testing project(s) via the InternalsVisibleTo assembly attribute. The takeaway is that you can still keep your API clean, as far as callers are concerned, while producing verifiable code.

Yes if ICollaborator needs several methods. If you have an object who's only job is to wrap a single method I'd rather see it replaced with a delegate though.
–
jk.Feb 28 '13 at 7:39

You'd have to decide if a named delegate make sense or if an interface makes sense, and I won't decide for you. Personally, I am not averse to single (public) method classes. The smaller the better, as they become increasingly easy to understand.
–
Anthony PegramFeb 28 '13 at 16:34

protected is almost the same as public. Only private and internal are implementation details.
–
CodesInChaosFeb 27 '13 at 17:08

@codeinchaos - I am curious here. For a test, protected methods are 'private' unless you modify assembly attributes. Only derived types have access to protected members. With the exception of virtual, I don't see why protected should be treated similar to public from a test. could you elaborate please?
–
Srikanth VenugopalanFeb 28 '13 at 1:37

Since those derived classes can be in different assemblies, they're exposed to third party code, and thus part of the public surface of your class. To test them, you can either make them internal protected, use a private reflection helper, or create a derived class in your test project.
–
CodesInChaosFeb 28 '13 at 8:21

@CodesInChaos, agreed that derived class can be in different assemblies, but the scope is still restricted to the base and derived types. Modifying the access modifier just to make it testable is something that I am a bit nervous about. I have done it, but it seems to be an antipattern to me.
–
Srikanth VenugopalanFeb 28 '13 at 8:25