与私有集合相关的单元测试 public 方法
Unit Test public methods related to a private collection
我的 class 有一个私有的惰性字典和一些与之交互的方法,如下所示
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;
}
}
这很有用,因为有时会发生一些插入的对象为空的情况,因此我避免添加它们来防止任何进一步的损坏。
现在我在测试阶段遇到了一个问题(我知道,我感到羞耻,我在测试前编写代码)因为我被迫在同一个测试中使用这两种方法:
[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);
}
...
}
最重要的是,我如何处理尝试插入字典中已有元素的测试?
[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.
}
最后我要问的是:
- 测试 RegisterObject 在里面调用 GetObject 是否正确?
- 如果我必须测试第二次插入被忽略,我该如何排列字典?
附带说明一下,我有 7 个单独的 RegisterObject 测试:
- RegisterObject_WithNullNameAndNullObject_DoNothing()
- RegisterObject_WithNullNameAndValidObject_DoNothing()
- RegisterObject_WithEmptyNameAndNullObject_DoNothing()
- RegisterObject_WithEmptyNameAndValidObject_DoNothing()
- RegisterObject_WithValidNameAndNullObject_DoNothing()
- RegisterObject_WithValidNameAndValidObject_RegisterObject()
- RegisterObject_AlreadyInserted_DoNothing()
太过分了?对这种简单行为的测试太多了吗?
Is correct to test RegisterObject calling GetObject inside it?
鉴于我们对 MyClass
的 public 接口的了解是它具有 RegisterObject
和 GetObject
,我认为您没有其他可以做。
即使你能做点别的,我也不会。您希望确保 class 以特定方式为其消费者服务,因此请像消费者一样使用它。这就是您判断它是否正常工作的方式。
How can i arrange the dictionary if i have to test that the second insertion is ignored?
从消费者的角度考虑这个问题。你想要发生什么?您似乎想表明,如果您在现有键下插入第二个对象,该方法会自动成功,但存储的值是原始值。我们怎么知道存储了什么?通过调用 GetObject
。所以我认为您进行的测试很好,但我会使用不同的值来插入。这样你就可以知道是否有任何改变。如果 GetObject
returns 原始值,则您的方法做对了。
我的 class 有一个私有的惰性字典和一些与之交互的方法,如下所示
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;
}
}
这很有用,因为有时会发生一些插入的对象为空的情况,因此我避免添加它们来防止任何进一步的损坏。 现在我在测试阶段遇到了一个问题(我知道,我感到羞耻,我在测试前编写代码)因为我被迫在同一个测试中使用这两种方法:
[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);
}
...
}
最重要的是,我如何处理尝试插入字典中已有元素的测试?
[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.
}
最后我要问的是:
- 测试 RegisterObject 在里面调用 GetObject 是否正确?
- 如果我必须测试第二次插入被忽略,我该如何排列字典?
附带说明一下,我有 7 个单独的 RegisterObject 测试:
- RegisterObject_WithNullNameAndNullObject_DoNothing()
- RegisterObject_WithNullNameAndValidObject_DoNothing()
- RegisterObject_WithEmptyNameAndNullObject_DoNothing()
- RegisterObject_WithEmptyNameAndValidObject_DoNothing()
- RegisterObject_WithValidNameAndNullObject_DoNothing()
- RegisterObject_WithValidNameAndValidObject_RegisterObject()
- RegisterObject_AlreadyInserted_DoNothing()
太过分了?对这种简单行为的测试太多了吗?
Is correct to test RegisterObject calling GetObject inside it?
鉴于我们对 MyClass
的 public 接口的了解是它具有 RegisterObject
和 GetObject
,我认为您没有其他可以做。
即使你能做点别的,我也不会。您希望确保 class 以特定方式为其消费者服务,因此请像消费者一样使用它。这就是您判断它是否正常工作的方式。
How can i arrange the dictionary if i have to test that the second insertion is ignored?
从消费者的角度考虑这个问题。你想要发生什么?您似乎想表明,如果您在现有键下插入第二个对象,该方法会自动成功,但存储的值是原始值。我们怎么知道存储了什么?通过调用 GetObject
。所以我认为您进行的测试很好,但我会使用不同的值来插入。这样你就可以知道是否有任何改变。如果 GetObject
returns 原始值,则您的方法做对了。