jeudi 9 avril 2015

Unit Test public methods related to a private collection

My class has a private lazy dictionary and some method to interact with it like this



public class MyClass : IExampleClass
{
private Lazy<Dictionary<string, IMyObject>> myObjects = new Lazy<Dictionary<string, IMyObject>>();
private Dictionary<string, IMyObject> MyObjects
{
get
{
return myObjects.Value;
}
}

public class MyClass()
{}

public void RegisterObject(string name, IMyObject object)
{
logger.LogInfo("Executed RegisterObject etc.");

if (String.IsNullOrEmpty(name) == false && object != null && MyObjects.ContainsKey(name) == false)
{
MyObjects.Add(name, object);
}
else
{
logger.LogWarning("Cannot register the object because etc.");
}
}

public IMyObject GetObject(string name)
{
logger.LogInfo("Executed GetObject etc.");

IMyObject obj = null;
if (String.IsNullOrEmpty(name) == false)
{
Objects.TryGetValue(name, out obj);
}

return obj;
}
}


This is something useful because sometimes happens that some of the inserted objects are null so i prevent any furter damage avoiding adding them. Now i'm facing a problem during the testing phase (i know, shame on me, i write code before test) because i'm forced to use both methods inside the same test:



[TestFixture]
public class MyClassTest
{
[Test]
public void RegisterObject_WithNullNameAndNullObject_DoNothing()
{
//Arrange
string inputName = null;
IMyObject inputObject = null;
IExampleClass sut = new MyClass();

//Act
sut.RegisterObject(inputName, inputObject);

//Assert
IMyObject actualValue = sut.GetObject(inputName);
Assert.IsNull(actualValue);
}

...
}


On top of that how can i handle the test where i'm trying to insert an element already in the dictionary?



[Test]
public void RegisterObject_AlreadyInserted_DoNothing()
{
//Arrange
string inputName = "test";
IMyObject inputObject = A.Dummy<IMyObject>();
IExampleClass sut = new MyClass();

// ???
sut.RegisterObject(inputName, inputObject);
// how can i effectively test the method if i'm using it more than once???

//Act
sut.RegisterObject(inputName, inputObject);

//Assert
IMyObject actualValue = sut.GetObject(inputName);

// ???
Assert.AreEqual(inputObject, actualValue);
// What i've tested here? The fact that the dictionary contains
// the object doesn't mean that the second call of RegisterObject
// is ignored.
}


So at end i'm asking:



  1. Is correct to test RegisterObject calling GetObject inside it?

  2. How can i arrange the dictionary if i have to test that the second insertion is ignored?


On a side note, i have 7 separate tests for RegisterObject:



  • RegisterObject_WithNullNameAndNullObject_DoNothing()

  • RegisterObject_WithNullNameAndValidObject_DoNothing()

  • RegisterObject_WithEmptyNameAndNullObject_DoNothing()

  • RegisterObject_WithEmptyNameAndValidObject_DoNothing()

  • RegisterObject_WithValidNameAndNullObject_DoNothing()

  • RegisterObject_WithValidNameAndValidObject_RegisterObject()

  • RegisterObject_AlreadyInserted_DoNothing()


It's overkill? Too many test for this simple behavior?


Aucun commentaire:

Enregistrer un commentaire