Skip to content

Commit

Permalink
Support DbSet Add/Remove/Find
Browse files Browse the repository at this point in the history
  • Loading branch information
rowanmiller committed Dec 8, 2014
1 parent 70876a9 commit 4d5a01d
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 11 deletions.
40 changes: 29 additions & 11 deletions src/EntityFramework.Testing.Moq/MockDbSetExtenstions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Moq;
using System;
using System.Collections.Generic;
using System.Data.Entity.Infrastructure;
using System.Linq;
Expand All @@ -14,12 +15,6 @@ public static MockDbSet<TEntity> SetupSeedData<TEntity>(
{
set.AddData(data);

// Need to re-setup LINQ if the data changes
if(set.IsLinqSetup)
{
set.SetupLinq();
}

return set;
}

Expand All @@ -32,22 +27,45 @@ public static MockDbSet<TEntity> SetupLinq<TEntity>(this MockDbSet<TEntity> set)
// Enable direct async enumeration of set
set.As<IDbAsyncEnumerable<TEntity>>()
.Setup(m => m.GetAsyncEnumerator())
.Returns(new TestDbAsyncEnumerator<TEntity>(set.Queryable.GetEnumerator()));
.Returns(() => new TestDbAsyncEnumerator<TEntity>(set.Queryable.GetEnumerator()));

// Enable LINQ queries with async enumeration
set.As<IQueryable<TEntity>>()
.Setup(m => m.Provider)
.Returns(new TestDbAsyncQueryProvider<TEntity>(set.Queryable.Provider));
.Returns(() => new TestDbAsyncQueryProvider<TEntity>(set.Queryable.Provider));

// Wire up LINQ provider to fall back to in memory LINQ provider of the data
set.As<IQueryable<TEntity>>().Setup(m => m.Expression).Returns(set.Queryable.Expression);
set.As<IQueryable<TEntity>>().Setup(m => m.ElementType).Returns(set.Queryable.ElementType);
set.As<IQueryable<TEntity>>().Setup(m => m.GetEnumerator()).Returns(set.Queryable.GetEnumerator());
set.As<IQueryable<TEntity>>().Setup(m => m.Expression).Returns(() => set.Queryable.Expression);
set.As<IQueryable<TEntity>>().Setup(m => m.ElementType).Returns(() => set.Queryable.ElementType);
set.As<IQueryable<TEntity>>().Setup(m => m.GetEnumerator()).Returns(() => set.Queryable.GetEnumerator());

// Enable Include directly on the DbSet (Include extension method on IQueryable is a no-op when it's not a DbSet/DbQuery)
// Include(string) and Include(Func<TEntity, TProperty) both fall back to string
set.Setup(s => s.Include(It.IsAny<string>())).Returns(set.Object);
return set;
}

public static MockDbSet<TEntity> SetupAddAndRemove<TEntity>(this MockDbSet<TEntity> set)
where TEntity : class
{
set.Setup(s => s.Add(It.IsAny<TEntity>()))
.Returns((TEntity t) => t)
.Callback((TEntity t) => set.AddData(t));

set.Setup(s => s.Remove(It.IsAny<TEntity>()))
.Returns((TEntity t) => t)
.Callback((TEntity t) => set.RemoveData(t));

return set;
}

public static MockDbSet<TEntity> SetupFind<TEntity>(this MockDbSet<TEntity> set, Func<object[], TEntity, bool> finder)
where TEntity : class
{
set.Setup(s => s.Find(It.IsAny<object[]>()))
.Returns((object[] keyValues) => set.Data.SingleOrDefault(e => finder(keyValues, e)));

return set;
}
}
}
10 changes: 10 additions & 0 deletions src/EntityFramework.Testing.Moq/MockDbSet`.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,19 @@ internal IQueryable<TEntity> Queryable
get { return _queryable; }
}

internal void AddData(TEntity data)
{
_data.Add(data);
}

internal void AddData(IEnumerable<TEntity> data)
{
_data.AddRange(data);
}

internal void RemoveData(TEntity data)
{
_data.Remove(data);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
</Otherwise>
</Choose>
<ItemGroup>
<Compile Include="FakeDbSetDataOperationsTests.cs" />
<Compile Include="FakeDbSetDataTests.cs" />
<Compile Include="FakeDbSetLinqTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
Expand Down
100 changes: 100 additions & 0 deletions test/EntityFramework.Testing.Moq.Tests/FakeDbSetDataOperationsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace EntityFramework.Testing.Moq.Tests
{
[TestClass]
public class FakeDbSetDataOperationsTests
{
[TestMethod]
public void Basic_add()
{
var set = new MockDbSet<Blog>()
.SetupAddAndRemove();

var blog = new Blog();
var result = set.Object.Add(blog);

Assert.AreSame(blog, result);
Assert.AreEqual(1, set.Data.Count());
Assert.IsTrue(set.Data.Contains(blog));
}

[TestMethod]
public void Basic_remove()
{
var blog1 = new Blog();
var blog2 = new Blog();
var data = new List<Blog> { blog1, blog2 };
var set = new MockDbSet<Blog>()
.SetupSeedData(data)
.SetupAddAndRemove();

var result = set.Object.Remove(blog1);

Assert.AreSame(blog1, result);
Assert.AreEqual(1, set.Data.Count());
Assert.IsFalse(set.Data.Contains(blog1));
Assert.IsTrue(set.Data.Contains(blog2));
}

[TestMethod]
public void Add_remove_work_with_enumeration()
{
var blog1 = new Blog();
var blog2 = new Blog();
var blog3 = new Blog();
var data = new List<Blog> { blog1, blog2 };
var set = new MockDbSet<Blog>()
.SetupSeedData(data)
.SetupLinq()
.SetupAddAndRemove();

set.Object.Remove(blog2);
set.Object.Add(blog3);

var result = set.Object.ToList();

Assert.AreEqual(2, result.Count);
Assert.IsTrue(result.Contains(blog3));
Assert.IsTrue(result.Contains(blog1));
}

[TestMethod]
public void Basic_find()
{
var blog = new Blog { BlogId = 1 };
var data = new List<Blog> { blog, new Blog { BlogId = 2 } };
var set = new MockDbSet<Blog>()
.SetupSeedData(data)
.SetupFind((keyValues, entity) => entity.BlogId == (int)keyValues.Single());

var result = set.Object.Find(1);

Assert.AreSame(blog, result);
}

[TestMethod]
public void Find_returs_null_for_no_match()
{
var data = new List<Blog>{ new Blog { BlogId = 1 }, new Blog { BlogId = 2 } };
var set = new MockDbSet<Blog>()
.SetupSeedData(data)
.SetupFind((keyValues, entity) => entity.BlogId == (int)keyValues.Single());

var result = set.Object.Find(99);

Assert.IsNull(result);
}

public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ namespace EntityFramework.Testing.Moq.Tests
[TestClass]
public class FakeDbSetDataTests
{
[TestMethod]
public void Data_is_addded_to_set()
{
var data = new List<Blog> { new Blog(), new Blog() };
Expand Down

0 comments on commit 4d5a01d

Please sign in to comment.