DbContext.Entry(foo).Reference(x => x.Bar).Load()的替代方案

时间:2016-01-06 15:22:47

标签: c# .net asp.net-mvc entity-framework entity-framework-6

我们正在尝试单元测试代码并继续https://msdn.microsoft.com/en-gb/data/dn314431https://msdn.microsoft.com/en-gb/data/dn314429我们遇到的问题我们正在使用In [7]: x = 3 * ureg.micrometre In [8]: "{:~}".format(x) Out[8]: '3 µm'

与此人... https://entityframework.codeplex.com/workitem/2741相同且与我的其他问题相关Loading Related Entities in Mocked DbContext using Moq for Web Api 2 Controller Tests u-导致我们出现问题。

在我们的Api控制器中,我们有以下操作

DbContext.Entry(foo).Reference(x=>x.Bar).Load()

我们只传递DbContext.Entry[ResponseType(typeof (Foo))] public async Task<IHttpActionResult> PostFoo(Foo foo) { _db.Foos.Add(foo); _db.Entry(foo).Reference(x => x.Bar).Load(); _db.Entry(foo).Reference(x => x.Qux).Load(); await _db.SaveChangesAsync(); return CreatedAtRoute("DefaultApi", new {id = foo.Id},foo); } 的FK,例如

BarId

但我们需要带回QuxIdvar newFoo = Foo{ Name = "New Foo", BarId = 1, Bar = null, QuxId = 2 Qux = null } 例如

Bar

所以使用Qux

有什么方法可以带回Foo { Name = "New Foo", BarId = 1, Bar = { BarId = 1, Name = "Super Bar", Description = "Super Bar 1"}, QuxId = 2, Qux = { QuxId = 2, Name = "Super Qux", Description = "Super Qux 2"}, } 以外的相关实体,或者我会更好地在_db.Entry(foo).Reference(x => x.Bar).Load();

之后阅读记录

延迟加载已被禁用。

1 个答案:

答案 0 :(得分:0)

在上一个问题Loading Related Entities in Mocked DbContext using Moq for Web Api 2 Controller Tests

中回答了这个问题

替换

....
_db.Foos.Add(foo);
_db.Entry(foo).Reference(x => x.Bar).Load();
_db.Entry(foo).Reference(x => x.Qux).Load();
await _db.SaveChangesAsync();
....

使用该功能的抽象

public interface IUnitOfWork {
    void Add<T>(T item) where T : class;
    void LoadRelatedEntity<T, TRelated>(T item, Expression<Func<T, TRelated>> exp)
        where T : class
        where TRelated : class;
    Task SaveChangesAsync();
}

喜欢这样

....
unitOfWork.Add(foo);
await unitOfWork.SaveChangesAsync();
unitOfWork.LoadRelatedEntity(foo, x => x.Bar);
unitOfWork.LoadRelatedEntity(foo, x => x.Qux);
....

设置测试

[TestMethod] 
public async Task TestPostFoo() {
     //Arrange
     bool saved = false;
     var model = new Foo {
         Name = "New Foo",
         QuxId = 99,
         Qux = null,
         BarId = 66,
         Bar = null
     };
     var mockUnitOfWork = new Moq.Mock<IUnitOfWork>();
     mockUnitOfWork.Setup(x => x.SaveChangesAsync())
         .Returns(() => Task.FromResult(0))
         .Callback(() => {
             model.Id = 1;
             saved = true;
         });
     mockUnitOfWork
         .Setup(x => x.LoadRelatedEntity<Foo, Qux>(It.IsAny<Foo>(), It.IsAny<Expression<Func<Foo, Qux>>>()))
         .Callback(() => model.Qux = new Qux() { QuxId = 2, Name = "Super Qux", Description = "Super Qux 2"});
     mockUnitOfWork
         .Setup(x => x.LoadRelatedEntity<Foo, Bar>(It.IsAny<Foo>(), It.IsAny<Expression<Func<Foo, Bar>>>()))
         .Callback(() => model.Bar = new Bar() { BarId = 1, Name = "Super Bar", Description = "Super Bar 1"});

     var controller = new TestsFooApiController(mockUnitOfWork.Object);
     controller.Request = new HttpRequestMessage { };
     controller.Configuration = new HttpConfiguration();

     //Act
     var result = await controller.PostFoo(model) as CreatedAtRouteNegotiatedContentResult<Foo>;

     //Assert
     result.Should().NotBeNull();
     result.Content.Should().NotBeNull();
     result.Content.Id.Should().BeGreaterThan(0);
     result.Content.Qux.Should().NotBeNull();
     result.Content.Bar.Should().NotBeNull();
     saved.Should().BeTrue(); 
}