1

I have a difficulty unit testing my class which contain a list of object.

Here is what I have

public class A 
{
    List<B> _list;

    public A() 
    {
        _list = new List<B>();
    }
    public void AddNewB(DateTime time)
    {
        _list.Add(new B(time));
    }
    public List<B> GetAllBs()
    {
        return _list;
    }
}

I want to have a test that prove that adding a new B doesn't clear my list. But since the list is private, I can't setup an existing list whitout going through the code I want to test. Since class A is responsible of creating all new B's and adding them to it's list and that all new A's should have an empty list of B's, adding a parameter in the constructor for the sake of testing feels weird.

Edit: I fixed GetAllBs since it was a copy-paste error of AddNewBs.

  • 3
    Remember that the unit you're testing is the class, not the method. So long as the public interface of the class behaves itself, you shouldn't care what it's doing internally. As far as your tests are concerned, `_list` might not even exist. – James Thorpe Mar 03 '17 at 16:06
  • You might want to read this http://stackoverflow.com/a/1093481/2096538. You shouldn't care about the internal implementation of the class, you should check if the externally visible effect matches your expectations, otherwise your tests are bound to the internal implementation of the class. – Daniel Wardin Mar 03 '17 at 16:08
  • I was feeling weird to call the method I want to test to setup my test. – Stéphane Pelletier-Lamothe Mar 03 '17 at 16:28

2 Answers2

4

First of all, this method won't compile:

public void GetAllBs(DateTime time)
{
    return _list;
}

It has return type void (returns nothing) but you return List<B>. Also, you don't need parameter to return result. Change it to:

public List<B> GetAllBs()

About testing: you can easily test your list. Your test method will be like this:

[TestMethod]
public void Test()
{
    A a = new A();
    a.AddNewB(DateTime.Now);    
    a.AddNewB(DateTime.Now); 

    Assert.AreEqual(2, a.GetAllBs().Count);
}

You should create object of class A and call AddNewB() to add some element. To be sure that list is not cleared after adding new element you should add one more and check Count of elements in the list. To do this you should call GetAllBs() - it will return list - and get Count. The Count should be equal to 2.

If you want to be sure that method is tested you can use some tool that shows code coverage(DotCover, OpenCover).

Roman
  • 11,966
  • 10
  • 38
  • 47
1

You can also use unit testing tools that allows you the fake private fields, for example I use Typemock that have this feature. so you can create a local list in the test and inject it to the private field in order to test your method:

[TestMethod]
public void TestMethod1()
{
    List<B> fakeList = new List<B> { new B(DateTime.Now), new B(new DateTime(1956, 01, 21)) };
    var classA = Isolate.Fake.Instance<A>(Members.CallOriginal,ConstructorWillBe.Ignored);

    var fakePrivate = Isolate.NonPublic.InstanceField(classA, "_list");
    fakePrivate.Value = fakeList;

    classA.AddNewB(DateTime.MaxValue);

    var res = classA.GetAllBs();

    Assert.AreEqual(3, res.Count);
}
Gregory Prescott
  • 574
  • 3
  • 10