如何对独立模型进行单元测试
本文关键字:单元测试 模型 独立 | 更新日期: 2023-09-27 18:32:03
我使用提到的存储库编写了以下方法在以下博客文章 (http://www.codecapers.com/post/Using-RavenDB-with-ASPNET-MVC.aspx) 中使用 RavenDB:
public User GetUserById(string id)
{
var user = (from usr in _repository.All<User>() where usr.Id == id select usr).FirstOrDefault();
if (user == null)
{
throw new NullReferenceException("No user with the id (" + id + ") could be found.");
}
return user;
}
您将如何使用 nunit(也许还有 moq)对此方法进行单元测试?
"用户"只是一个普通类。
通常,您不会直接针对存储库层编写测试。例如,假设您正在使用nHibernate或实体框架,那么针对存储库进行测试在技术上将测试该框架。
创建者或那些ORM已经做到了。
此外,与数据库通信会使测试成为集成测试而不是单元测试。
例如,您的单元测试将针对模拟存储库层的业务层。
如果你想写一个集成测试,你也可以针对业务层编写它,但不要嘲笑存储库层并让它通过。
我会执行以下操作来准备您的代码:
- 确保
_repository
是通过构造函数或属性传入的,以便可以轻松更改它进行测试。 - 确保将
_repository
变量声明为IRepository
类型,而不是具体类型。
然后,在测试中:
- 创建界面的模拟并将其传递给您的
_repository
。 - 重写
.All<User>()
方法以返回已知的硬编码User
列表,其中包含适合测试的值。 - 在一个测试中断言查询现有 ID 时返回正确的值。
- 在单独的测试中断言,查询不存在的 ID 时会引发异常。
第一个问题是 - 在这种情况下,您正在测试什么?提供的方法实际上只有两个结果,因此您基本上是在测试user
是否为空。这是增值测试吗?
至于如何,我假设_repository
是通过某种机制注入的?如果是这样,那么您只需提供一个Mock<IRepository>
(根据需要插入您的类型名称),并在注入_repository
的位置注入它。然后,您可以设置返回值并测试您的方法是否存在异常。
mockRepository.Setup(x => x.All<User>()).Returns(new List<User> { ... });
RavenDB 是专门设计的,因此您无需模拟所有单元测试。
只需在内存中运行它,然后可以直接对它执行单元测试。有关详细信息,请参阅此博客文章。
它允许您编写如下代码:
[Fact]
public void CanQueryForDistinctItemsUsingLinq()
{
using (var store = NewDocumentStore())
{
using (var s = store.OpenSession())
{
s.Store(new { Name = "ayende" });
s.Store(new { Name = "ayende" });
s.Store(new { Name = "rahien" });
s.SaveChanges();
}
store.DocumentDatabase.PutIndex("test", new IndexDefinition
{
Map = "from doc in docs select new { doc.Name }",
Stores = { { "Name", FieldStorage.Yes } }
});
using (var s = store.OpenSession())
{
var objects = s.Query<User>("test")
.Customize(x => x.WaitForNonStaleResults())
.Select(o => new {o.Name })
.Distinct()
.ToList();
Assert.Equal(2, objects.Count);
Assert.Equal("ayende", objects[0].Name);
Assert.Equal("rahien", objects[1].Name);
}
}
}
这来自RavenDB单元/集成测试,所以你需要一些信息才能让它工作,但它给出了一般的想法。