简体   繁体   中英

How to Unit Test without Hitting Database

I want to ask what is a good unit test for the method below where interim identifier is a string -- such as 78th2015. 下面的方法(其中的临时标识符是一个字符串)是一个好的单元测试-例如78th2015。

We are setup to use the interface IMeetingsService. We are using MOQ and 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);

    }

}

Edit:

But I am not sure how to set it up. This result is not null, but what does it do for me?

[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);
} 

Use Mocking , that's what it is for. Use JMock or Mockito or any other library you prefer.

Create a Mock<IInterimCommitteeDbContext> and pass it into the constructor. On this object setup the Meetings and Committees properties to return various collections.

You should have different tests setup that return different collections. For example, how should this behave if both the Meetings and Committees are empty, ie there is no data in the database? How should it behave if there isn't an object with the provided InterimIdentifier ? What about if there is one that matches etc.

I figured out how to do this using test doubles. I am using Entity Framework 6 with the code first model. I created a DbContext that inherited from my I-DbContext interface. Then I was able to create in-memory data to use in my service layer unit tests. Below is an example of:

  1. the test data context,
  2. the test dbset,
  3. an example unit test.

This solution was available from an msdn article here: https://msdn.microsoft.com/en-us/data/dn314429.aspx ...

public class CommitteeContextTest : ICommitteeDbContext
        {
            public CommitteeContextTest()
            {
                this.Committees = new TestDbSet();
                this.CommitteeMembers = new TestDbSet();
            }
            public Database Database { get; }
            public DbSet Committees { get; set; }
            public DbSet CommitteeMembers { get; set; }
        }
    }
public class TestDbSet : DbSet, IQueryable, IEnumerable, IDbAsyncEnumerable
            where TEntity : class
    {
        ObservableCollection _data;
        IQueryable _query;

        public TestDbSet()
        {
            _data = new ObservableCollection();
            _query = _data.AsQueryable();
        }

        public override TEntity Add(TEntity item)
        {
            _data.Add(item);
            return item;
        }

        public override TEntity Remove(TEntity item)
        {
            _data.Remove(item);
            return item;
        }

        public override TEntity Attach(TEntity item)
        {
            _data.Add(item);
            return item;
        }

        public override TEntity Create()
        {
            return Activator.CreateInstance();
        }
    }

    [TestClass]
    public class CommitteeServiceTest
    {
        private InterimCommitteeContextTest _interimCommitteeContext;
        private ICommitteeService _service;
        private string _interim;

        [TestInitialize]
        public void SetUp()
        {
            _interimCommitteeContext = new InterimCommitteeContextTest();
            _service = new CommitteeService(_interimCommitteeContext);
            _interim = Settings.Default.DefaultInterimIdentifier;
        }

        [TestCleanup]
        public void Teardown()
        {
            _interimCommitteeContext = null;
            _service = null;
        }

        [TestMethod]
        public void GetCommittee_ProvideInterimCommitteeId_ReturnOneCommittee()
        {
            //Arrange
            AddCommittees();

            //Act and Assert
            var result = _service.GetCommittee(_interim, 1);
            Assert.AreEqual(1, result.CommitteeId); //Passes.  IsActive set to true;
            result = _service.GetCommittee(_interim, 0);
            Assert.IsNull(result); //Fails.  No committeeId = 0;
            result = _service.GetCommittee(_interim, 2);
            Assert.IsNull(result); //Fails.  CommitteeId = 2 is not active.
        }

        [TestMethod]
        public void 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 });
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM