How can I correctly unit test methods that depend on each other?

Consider this code:

private readonly Dictionary<Type, Component> _components = new Dictionary<Type, Component>(); public Component this [Type type] { get { Component component; _components.TryGetValue(type, out component); return component; } } public void AddComponent(Component component) { _components.Add(component.GetType(), component); } 

As you can see, AddComponent adds AddComponent to the private variable. But the only way to check this is with an indexer. This is good, but in order to test the indexer, I would have to call AddComponent too!

In other words, in unit tests for the indexer and AddComponent each test would have to call both of these methods. This seems to create an unnecessary connection. If there is an error in the index, there is no reason for my TestAddComponent .

What is the best practice here? Do I use reflection to get to _components ? Tantalizing? Something else?

+7
source share
6 answers

You have 2 options:

  • Use reflection or private access classes of the MSTest class to get and set private field values โ€‹โ€‹during the test.
  • Just donโ€™t worry about it and do not test the exposed behavior, even if it means that your test depends on other properties or a method that are tested elsewhere.

As you can probably tell from the wording, my choice would be with No. 2 - you have to check the behavior . In your case, the testable behavior you are testing is:

  • If I use AddComponent , then the added component should be accessible using an indexer
  • If I use an indexer, I must have access to any components that have been added through AddComponent

In this case, it is pretty obvious that this is almost the same thing, so we really only have one case with the case / exposed behavior for testing here. Yes, this unit test covers two different things, but it does not really matter - we are not trying to verify that each method / property behaves as expected, rather we want to verify that each open behavior works as expected.


Alternatively, suppose we go for option 1 and used personal reflection to check the state of the _components themselves. In this case, the bevahour we are actually testing is:

  • If I use AddComponent , the added component should be added in _components
  • If I use an index, I must have access to any components found in _components

We not only test the internal behavior of the class (so if the implementation changes, the tests fail even if the class works as expected), but we just doubled the number of tests we write.

In addition, increasing the complexity of our tests, we increase the likelihood that the tests themselves have a mistake - for example, what if we made a mistake in test 2. did we check several completely different private fields? In this case, we not only did more work for ourselves, but we donโ€™t even check the actual behavior that we want to check!

+6
source

In my opinion, unit tests should not reflect in order to force its goals . I think that in this type of test both should be tested in the tag , in the same test. But this is just a point of view.

However, you can perform several tests by changing the order of the instructions. Try adding a few, and access is first, then last, then one from the middle. Each test is one scenario, with a different order, the number of inserts. You can even check for exceptional conditions that should happen ... for example, if you try to get something that has not been inserted.

I think unit test exists to simulate usage or to provide specification . Not to see if every bit of the program is correct, because it kills flexibility.

+7
source

When you use the Microsoft Unit Test Framework, the environment creates a private accessor class. This should allow you to access your personal types. Take a look at this page from Microsoft for more information:

http://msdn.microsoft.com/en-us/library/dd293546.aspx

Specifically in this section: Create unit tests that can appeal to internal, private, and friends.

+2
source

May I suggest using interfaces or virtual methods and MOQ. This way you can MOQ call methods you donโ€™t want to test, and force them to return what you want.

+1
source

There are two options.

  • Test the functionality together, as already mentioned.
  • Change your class so that you can wrap it in test tape.

The test harness should be determined using your unit tests and expose the elements necessary to verify the functionality of the functionality. You should use test wiring instead of class directly in your unit tests.

 public class MyClass { protected readonly Dictionary<Type, Component> _components = new Dictionary<Type, Component>(); public Component this [Type type] { get { Component component; _components.TryGetValue(type, out component); return component; } } public void AddComponent(Component component) { _components.Add(component.GetType(), component); } } public class MyClassTestHarness : MyClass { public Dictionary<Type, Component> Components { get { return _components; } } } 

I forgot to mention another option, which is an injection of dependencies with a mockery. If you want to make fun of IDictionary, you can test your test.

 public class MyClass { protected IDictionary _components; public MyClass() { _components = new Dictionary(); } public MyClass(IDictionary components) { _components = components; } public Component this [Type type] { get { Component component; _components.TryGetValue(type, out component); return component; } } public void AddComponent(Component component) { _components.Add(component.GetType(), component); } } 
+1
source

If you want to do it this way, go from the class to the constructor (ignoring the IoC framework at the moment) and use the interface to refer to the dependency:

 class ComponentManager { private readonly IDictionary<Type, Component> _components; public ComponentManager() : this(new Dictionary<Type, Component>()) { } public ComponentManager(IDictionary<Type, Component> components) { _components = components; } public Component this[Type type] { get { Component component; _components.TryGetValue(type, out component); return component; } } public void AddComponent(Component component) { _components.Add(component.GetType(), component); } } 

Now you can make fun of addiction and test interactions.

However, given the lack of added behavior, I believe that a really practical approach is to directly open the member and discard aggregated objects:

 class ComponentManager { public Dictionary<Type, Component> Components { get; private set; } public ComponentManager() { Components = new Dictionary<Type, Component>(); } } 
+1
source

All Articles