【问题标题】:How to Unit Test without Hitting Database如何在不访问数据库的情况下进行单元测试
【发布时间】:2015-09-21 16:09:27
【问题描述】:

我想问一下 GetMeetingsByInterimIdentifier 下面的方法什么是好的单元测试,其中临时标识符是一个字符串——例如 78th2015。

我们设置为使用接口 IMeetingsService。我们正在使用 MOQ 和 Microsoft.VisualStudio.TestTools.UnitTesting。

public class MeetingsService : IMeetingsService
{
    private readonly IInterimCommitteeDbContext _db;

    public MeetingsService(IInterimCommitteeDbContext db)
    {
        this._db = db;
    }

    public IQueryable<Meeting> GetMeetingsByInterimIdentifier(string interimIdentifier)
    {
        return
            from m in this._db.Meetings
            join c in this._db.Committees on m.CommitteeId equals c.CommitteeId
            where c.InterimIdentifier == interimIdentifier
            select m;
    }

    public Meeting GetMeeting(int meetingKey)
    {
        return this._db.Meetings.FirstOrDefault(x => x.MeetingId == meetingKey);

    }

}

编辑:

但我不确定如何设置它。这个结果不为空,但它对我有什么作用?

[TestMethod] 
public void GetMeetingsByInterimIdentifier_WithInterimIdentifier_ReturnsMeetingList() 
{ 
    //Arrange 
    var interim = Properties.Settings.Default.DefaultInterimIdentifier; 
    var result = _meetingServiceMock.Setup(x => x.GetMeetingsByInterimIdentifier(interim)); 

    //Act 

    //Assert 
    Assert.IsNotNull(result);
} 

【问题讨论】:

  • 我可能不会费心对此进行单元测试。您正在测试基于过滤器 (interimIdentifier) 从 EF 返回的数据库对象。您的代码不会在 LINQ 语句执行后操纵结果,因此您最好创建一个实际命中数据库的集成测试。

标签: c# unit-testing moq mstest


【解决方案1】:

创建一个Mock&lt;IInterimCommitteeDbContext&gt; 并将其传递给构造函数。在此对象上设置 MeetingsCommittees 属性以返回各种集合。

您应该有不同的测试设置来返回不同的集合。例如,如果MeetingsCommittees 都是空的,即数据库中没有数据,这应该如何表现?如果提供的InterimIdentifier 没有对象,它应该如何表现?如果有一个匹配的等等呢?

【讨论】:

  • 但我什至不知道如何设置它。这不起作用:
  • 也许将您目前所拥有的内容添加到问题中,或者使用您所拥有的内容创建一个新问题?
  • 但我不知道如何设置它。这个结果不为空,但它对我有什么作用? [TestMethod] public void GetMeetingsByInterimIdentifier_WithInterimIdentifier_ReturnsMeetingList() { //Arrange var interim = Properties.Settings.Default.DefaultInterimIdentifier; var 结果 = _meetingServiceMock.Setup(x => x.GetMeetingsByInterimIdentifier(interim)); //Act //断言 Assert.IsNotNull(result); }
【解决方案2】:

我想出了如何使用测试替身来做到这一点。我正在使用 Entity Framework 6 和代码优先模型。我创建了一个继承自 I-DbContext 接口的 DbContext。然后我能够创建内存数据以在我的服务层单元测试中使用。下面是一个例子:

  1. 测试数据上下文,
  2. 测试数据库集,
  3. 一个示例单元测试。

此解决方案可从此处的 msdn 文章中获得: https://msdn.microsoft.com/en-us/data/dn314429.aspx ...

公共类 CommitteeContextTest : ICommitteeDbContext { 公共委员会上下文测试() { this.Committees = new TestDbSet(); this.CommitteeMembers = new TestDbSet(); } 公共数据库数据库{get; } 公共 DbSet 委员会 { 获取;放; } 公共 DbSet 委员会成员 { 获取;放; } } } 公共类 TestDbSet:DbSet、IQueryable、IEnumerable、IDbAsyncEnumerable 其中 TEntity :类 { ObservableCollection _data; IQueryable _query; 公共测试数据库集() { _data = new ObservableCollection(); _query = _data.AsQueryable(); } 公共覆盖 TEntity 添加(TEntity 项) { _data.Add(项目); 归还物品; } 公共覆盖 TEntity 删除(TEntity 项) { _data.Remove(项目); 归还物品; } 公共覆盖 TEntity Attach(TEntity 项) { _data.Add(项目); 归还物品; } 公共覆盖 TEntity Create() { 返回 Activator.CreateInstance(); } } [测试类] 公共类 CommitteeServiceTest { 私有 InterimCommitteeContextTest _interimCommitteeContext; 私人 ICommitteeService _service; 私有字符串_interim; [测试初始化​​] 公共无效设置() { _interimCommitteeContext = new InterimCommitteeContextTest(); _service = new CommitteeService(_interimCommitteeContext); _interim = Settings.Default.DefaultInterimIdentifier; } [测试清理] 公共无效拆解() { _interimCommitteeContext = null; _service = null; } [测试方法] 公共无效 GetCommittee_ProvideInterimCommitteeId_ReturnOneCommittee() { //安排 添加委员会(); //行为和断言 var 结果 = _service.GetCommittee(_interim, 1); Assert.AreEqual(1, result.CommitteeId); //通过。 IsActive 设置为 true; 结果 = _service.GetCommittee(_interim, 0); 断言.IsNull(结果); //失败。没有委员会ID = 0; 结果 = _service.GetCommittee(_interim, 2); 断言.IsNull(结果); //失败。 CommitteeId = 2 未激活。 } [测试方法] 公共无效 AddCommittees() { _interimCommitteeContext.Committees.Add(new Committee() { CommitteeId = 1, InterimIdentifier = _interim, IsActive = true, CommitteeTypeId = 1 }); _interimCommitteeContext.Committees.Add(new Committee() { CommitteeId = 2, InterimIdentifier = _interim, IsActive = false, CommitteeTypeId = 1 }); _interimCommitteeContext.Committees.Add(new Committee() { CommitteeId = 3, InterimIdentifier = _interim, IsActive = true, CommitteeTypeId = 1 }); } }

【讨论】:

    【解决方案3】:

    使用Mocking,这就是它的用途。使用 JMockMockito 或您喜欢的任何其他库。

    【讨论】:

    • 这不是答案,更多的是;您为 OP 提供了一个不相关的框架,因为他使用 C# 而不是 Java 并且在 SO 中单行不是答案......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多