我正在使用moq,但无法进行verifyAll
方法调用。我不知道我做错了什么。
要测试的类:
namespace ConsoleApplication2
{
public class SomeUtil
{
public static List<Person> underAgePerson = new List<Person>();
public static List<Person> females = new List<Person>();
public static List<Person> males = new List<Person>();
public static List<Person> deletePersons = new List<Person>();
public SomeAdapter adapter;
public SomeUtil()
{
this.adapter = new SomeAdapter();
}
public void Valid(List<Person> persons)
{
foreach (Person p in persons)
{
if (p.Name == null)
{
deletePersons.Add(p);
}
if (p.Age < 18)
{
if (!deletePersons.Contains(p))
{
deletePersons.Add(p);
}
underAgePerson.Add(p);
}
adapter.SetGender(p);
if (p.Gender.Equals("Male", StringComparison.InvariantCultureIgnoreCase))
{
males.Add(p);
}
else if (p.Gender.Equals("Female", StringComparison.InvariantCultureIgnoreCase))
{
females.Add(p);
}
}
foreach (Person p in deletePersons)
{
persons.Remove(p);
}
deletePersons.Clear();
}
}
}
SomeUtil类:
namespace ConsoleApplication2
{
public class SomeAdapter
{
public virtual Person SetGender(Person p)
{
if (string.IsNullOrEmpty(p.Gender))
{
p.Gender = "Male";
}
return p;
}
}
}
单元测试:
[TestClass]
public class SomeUtilTest
{
Mock<SomeAdapter> adapter;
List<Person> persons;
SomeUtil util;
[TestInitialize]
public void Initialize()
{
adapter = new Mock<SomeAdapter>();
persons = new List<Person>();
util = new SomeUtil();
}
[TestCleanup]
public void CleanUp()
{
adapter.VerifyAll();
}
[TestMethod]
public void Valid_WithEmptyName_ShouldRemove()
{
Person person = new Person();
person.Gender = "";
person.Age = 1;
persons.Add(person);
Person result = new Person();
result.Age = 19;
result.Gender = "Female";
result.Name = "Dannie";
adapter.Setup(a => a.SetGender(person)).Returns(result);
int count = persons.Count;
util.Valid(persons);
Assert.AreEqual(count - 1, persons.Count);
}
}
答案 0 :(得分:2)
public SomeUtil()
{
this.adapter = new SomeAdapter();
}
因为你有新的SomeAdapter而没有注入SomeUtil类,所以你要验证的模拟不是代码中与之交互的实例,它是一个完全不同的对象。
您需要通过构造函数或属性注入以某种方式注入SomeAdapter依赖项。您可以手动执行此操作,例如
在SomeUtil.cs
中 public SomeUtil(SomeAdaptor adaptor)
{
this.adapter = adaptor;
}
在测试设置中:
[TestInitialize]
public void Initialize()
{
adapter = new Mock<SomeAdapter>();
persons = new List<Person>();
util = new SomeUtil(adapter.Object);
}
然而,理想情况下,您不会嘲笑和注入实体类,而是接口或抽象类型。此外,在您的应用程序(而不是测试)中,您可能希望使用像Ninject或Windsor这样的DI框架(自从我做.NET以来已经有一段时间了,所以现在可能有不同的选项)。
克里斯
答案 1 :(得分:2)
这是因为您的SomeUtil类使用的是真正的SomeAdapter类,而不是Mock类。 Moq无法观察真实类中方法的用法。
您需要做的是将SomeAdapter的实例注入SomeUtil类。而不是:
public SomeAdapter adapter;
public SomeUtil()
{
this.adapter = new SomeAdapter();
}
这样做:
public SomeAdapter adapter;
public SomeUtil(SomeAdapter adapter)
{
this.adapter = adapter;
}
然后,在单元测试中:
[TestInitialize]
public void Initialize()
{
adapter = new Mock<SomeAdapter>();
persons = new List<Person>();
util = new SomeUtil(adapter.Object);
}
请注意adapter.Object
的使用。这为您提供了Moq观察到的类的实例。
如果您进行了这些更改,您的单元测试将通过。但是dependency inversion这里有一个更深层次的基本原则,我鼓励你去研究。在许多方面,它使得使用模拟测试库更容易使用。