2017-10-19 85 views
3

我有entityframework回购,它从sqldb获取行程信息。我创建了repo,并在构造函数中注入了dbContext并使用该上下文执行数据库操作。为EF dbcontext设置模拟对象以测试存储库方法

public class WorldRepository : IWorldRepository 
    { 
     private WorldContext _context; 

     public WorldRepository(WorldContext context) 
     { 
      _context = context; 
     } 

     public void AddSop(string tripName, Stop newStop) 
     { 
      var trip = GetTipByName(tripName); 

      if (trip != null) 
      { 
       trip.Stops.Add(newStop); 
       _context.Stops.Add(newStop); 
      } 
     } 

     public void AddTrip(Trip trip) 
     { 
      _context.Add(trip); 
     } 

     public IEnumerable<Trip> GetAllTrips() 
     { 
      return _context.Trips.ToList(); 
     } 
} 

现在我正在尝试使用最小起订量,但这没有帮助。我无法测试任何写入我的方法的逻辑,因为它查询的是模拟对象而不是我的实现。

// private Mock<IWorldRepository> _mockWorld; 

     [TestMethod] 
     public void Test_AddTrips() 
     { 
      //Arrange 
      // WorldRepository repo = new WorldRepository(null); 

      Mock<IWorldRepository> _mockWorld = new Mock<IWorldRepository>(); 
      var repo = _mockWorld.Object; 

      //Act 
      repo.AddSop("Sydney", new Stop 
      { 
       Arrival = DateTime.Now, 
       Id = 2, 
       Latittude = 0.01, 
       Longitude = 0.005, 
       Name = "Test Trip", 
       Order = 5 
      }); 

      repo.SaveChangesAsync(); 

      var count = repo.GetAllTrips().Count(); 

      //Assert 
      Assert.AreEqual(1, count); 


     } 

这是WorldContext的代码。

public class WorldContext:DbContext 
    { 
     private IConfigurationRoot _config; 

     public WorldContext(IConfigurationRoot config,DbContextOptions options) 
      :base(options) 
     { 
      _config = config; 
     } 

     public DbSet<Trip> Trips { get; set; } 
     public DbSet<Stop> Stops{ get; set; } 

     protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) 
     { 
      base.OnConfiguring(optionsBuilder); 
      optionsBuilder.UseSqlServer(_config["ConnectionStrings:WorldCotextConnection"]); 
     } 
    } 
+2

您需要使用WorldRepository类和模拟dbcontext。您还可以发布WorldContext的代码。 – Simsons

+2

您应该嘲笑WorldContext并将其传递到WorldRepository中。 – HiredMind

+1

Microsoft为异步模拟提供了一个实现。 https://msdn.microsoft.com/en-us/library/dn314429(v=vs.113).aspx – Jasen

回答

2

我假设你正在试图嘲弄WorldContextand与您的回购情况下使用它,所以我们需要模拟,第一。要做到这一点,请为worlddbcontext创建一个接口。

public interface IWorldContext 
    { 
     DbSet<Stop> Stops { get; set; } 
     DbSet<Trip> Trips { get; set; } 
    } 

现在你想要的是嘲笑依赖和测试主题。

在这种情况下,您想模拟WorldDbContext,模拟DbSet<Stop>并测试AddSop方法。

要创建一个模拟DbSet,我在引用MSDN, EF Testing with Mocking framework也提到了Jasen的注释。

private Mock<IWorldContext> _context; 
private WorldRepository _repo; 

     [TestMethod] 
     public void Test_AddTrips() 
     { 
      ////Arrange   

      var data = new List<Stop> { 
       new Stop 
       { 
        Arrival = DateTime.Now.AddDays(-15), 
        Id = 1, 
        Latittude = 0.05, 
        Longitude = 0.004, 
        Name = "Test Trip01", 
        Order = 1 
       }, 
        new Stop 
       { 
        Arrival = DateTime.Now.AddDays(-20), 
        Id = 2, 
        Latittude = 0.07, 
        Longitude = 0.015, 
        Name = "Test Trip02", 
        Order = 2 
       } 

      }.AsQueryable(); 

      var mockSet = new Mock<DbSet<Stop>>(); 
      mockSet.As<IQueryable<Stop>>().Setup(m => m.Provider).Returns(data.Provider); 
      mockSet.As<IQueryable<Stop>>().Setup(m => m.Expression).Returns(data.Expression); 
      mockSet.As<IQueryable<Stop>>().Setup(m => m.ElementType).Returns(data.ElementType); 
      mockSet.As<IQueryable<Stop>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator()); 


      _context = new Mock<IWorldContext>(); 

      //Set the context of mock object to the data we created. 
      _context.Setup(c => c.Stops).Returns(mockSet.Object); 

      //Create instance of WorldRepository by injecting mock DbContext we created 
      _repo = new WorldRepository(_context.Object);  


      //Act 
      _repo.AddSop("Sydney", 
       new Stop 
       { 
        Arrival = DateTime.Now, 
        Id = 2, 
        Latittude = 0.01, 
        Longitude = 0.005, 
        Name = "Test Trip", 
        Order = 5 
       }); 

      _repo.SaveChangesAsync(); 

      var count = _repo.GetAllTrips().Count(); 

      //Assert 
      Assert.AreEqual(3, count); 


     } 

另外,有一个辉煌的module上的多个视线上Testing Repository模块,他非常详细地解释了这个(仅仅是一个参考,没有背书或其他任何东西)的Mosh

1

如果你想测试WorldRepository,你需要创建这种类型的真实对象,并模拟它的所有外部依赖关系 - WorldContext在你的情况。

为测试所以正确的设置应该是这样的:

var contextMock = new Mock<WorldContext>(); 
contextMock.Setup(...); //setup desired behaviour 
var repo = new WorldRepository(contextMock.Object);