First of all, it is important to understand why you want to cover these methods with unit tests, because this will affect the answer. Only you and your team know this, but if we assume that at least part of the motivation for unit testing is to get a reliable set of regression tests , you should check the behavior of the observed behavior of the system under test (SUT).
In other words, unit tests should be black boxes . Tests do not need to know about the details of the implementation of SUT. So the naive conclusion you could draw from this is that if you have duplicate behavior, you should also have a repeating test code.
However, the more complex your system, the more it depends on the general behavior and strategies, the more difficult it is to implement this testing strategy. This is because you will have a combinatorial explosion of possible paths through the system. JB Rainsberger explains this better than me .
The best alternative is often to listen to your tests (a concept popularized by GOOS ). In this case, it seems to be useful to extract the general behavior into a public method. This, however, does not in itself solve the problem of the combinatorial explosion. While you can test the general behavior in isolation, you also need to prove that the two original methods ( Add and Update ) use the new public method (and not, for example, some code with copy and paste).
The best way to do this is to compose methods with a new strategy:
public class Host<T> { private readonly IHelper<T> helper; public Host(IHelper<T> helper) { this.helper = helper; } public void Add(T item) {
(Obviously, you need to give type names and methods better names.)
This allows you to use Behavior Verification to prove that the Add and Update methods correctly use the AddOrUpdate method:
[TestMethod] public void AddT_HasBehaviorA() { var mock = new Mock<IHelper<object>>(); var sut = new Host<object>(mock.Object); var item = new object(); sut.Add(item); mock.Verify(h => h.AddOrUpdate(item)); } [TestMethod] public void UpdateT_HasBehaviorA() { var mock = new Mock<IHelper<object>>(); var sut = new Host<object>(mock.Object); var item = new object(); sut.Update(item); mock.Verify(h => h.AddOrUpdate(item)); }
Mark seemann
source share