Reputation: 12661
This is inspired by some work I did with a client who liked writing unit tests according to the scheme:
One test class per class under test; one nested class per public method.
So the test classes would look something like this:
public class TestWidget
{
private Mock<IDoSomething> _mockSomethingDoer = new Mock<IDoSomething>();
private Widget _widget = new Widget(_mockSomethingDoer);
public class OpenCan : TestWidget
{
[Fact]
public void GeneratesFroth()
{
// ARRANGE
_mockSomethingDoer.SetUp(...);
// ACT
_widget.OpenCan();
// ASSERT
_widget.Should().Have().Generated().Froth();
}
[Fact]
public void DoesNotSpillEverywhere()
{
// ARRANGE
_mockSomethingDoer.SetUp(...);
// ACT
_widget.OpenCan();
// ASSERT
_widget.Should().Not.Have().Spilled().Everywhere();
}
}
}
It's a nice scheme, but something about it confuses me. Why does the OpenCan
class have access to the private members of TestWidget
? It's not because it is a nested class. Take away the derivation from TestWidget
and the code will no longer compile. It can't be because it is a derived class: the very definition of private scope forbids access by derived classes. However, if OpenCan
is both nested and derived, it somehow magically gains access to the private member variables of TestWidget
.
Is this a deliberate feature of the language, or an unexpected side effect?
Upvotes: 0
Views: 170
Reputation: 16498
A nested or inner class has access to the enclosing class' private members. The reason removing inheritance breaks your code is there is no context for accessing the private members (i.e. you don't have an instance of TestWidget
with which to access the instance properties/members). If you made private static members in TestWidget
, they would be accessible from OpenCan
without inheriting from TestWidget
Example of member accessibility (not necessarily useful or a good idea, but it demonstrates the feature):
public class Outer
{
private int OuterProperty { get; set; }
public class Inner
{
public void UpdateOuter( Outer outer, int value )
{
outer.OuterProperty = value;
}
}
}
Upvotes: 3