使用moq通用存储库和UnitOfWork进行单元测试

时间:2017-05-21 17:06:16

标签: c# moq repository-pattern unit-of-work nunit-3.0

我有一个特定的通用存储库:

通用存储库:

public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
    protected readonly DbContext Context;
    private DbSet<TEntity> _entities;

    public Repository(DbContext context)
    {
        Context = context;
        _entities = Context.Set<TEntity>();
    }

    public IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate)
    {
        return _entities.Where(predicate);
    }
}

特定存储库:

public class HolidayCalendarRepository : Repository<HolidayCalendar>, IHolidayCalendarRepository
{
    public HolidayCalendarRepository(ApplicationDbContext context)
        : base(context)
    {
    }

    public ApplicationDbContext ApplicationDbContext
    {
        get { return Context as ApplicationDbContext; }
    }

    public bool IsHoliday(DateTime date)
    {
        return Find(h => h.Date == date.Date).Any();
    }
}

IRepository

public interface IRepository<TEntity> where TEntity : class
{       
    IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate);
}

IHolidayCalendarRepository

public interface IHolidayCalendarRepository : IRepository<HolidayCalendar>
{
    bool IsHoliday(DateTime date);                     
}

的UnitOfWork

public class UnitOfWork : IUnitOfWork
{
    private readonly ApplicationDbContext _context;

    public UnitOfWork(ApplicationDbContext context)
    {
        _context = context;          
        HolidayCalendars = new HolidayCalendarRepository(_context);
    }

    public IHolidayCalendarRepository HolidayCalendars { get; private set; }

    public int Complete()
    {
        return _context.SaveChanges();
    }

    public void Dispose()
    {
        _context.Dispose();
    }
}

如何在我的存储库上测试方法 IsHoliday(DateTime date)。 我是单元测试的初学者。这是我尝试但它不起作用。

[TestFixture]
public class HolidayCalendarRepositoryTests
{
    private HolidayCalendarRepository _holidayCalendarRepository;
    private Mock<DbSet<HolidayCalendar>> _mockHolidayCalendar;

    [SetUp]
    public void TestInitialize()
    {          
        var mockContext = new Mock<ApplicationDbContext>();
        _mockHolidayCalendar = new Mock<DbSet<HolidayCalendar>>();


        mockContext.Setup(hc => hc.HolidayCalendar).Returns(_mockHolidayCalendar.Object);
        _holidayCalendarRepository = new HolidayCalendarRepository(mockContext.Object);

    }

    [Test]
    public void IsHoliday_CurrentDateIsHoliday_ShouldBeTrue()
    {
        var holidays = new List<HolidayCalendar>() { new HolidayCalendar { ID = 1, Date = DateTime.Today } };

        _mockHolidayCalendar.SetSource(holidays);

        var result = _holidayCalendarRepository.IsHoliday(DateTime.Today);

        Assert.IsTrue(result);
    }
}

SetSource方法

    public static void SetSource<T>(this Mock<DbSet<T>> mockSet, IList<T> source) where T : class
    {
        var data = source.AsQueryable();

        mockSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(data.Provider);
        mockSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(data.Expression);
        mockSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(data.ElementType);
        mockSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
    }

1 个答案:

答案 0 :(得分:2)

根据过去的经验,看起来上下文的设置没有正确完成。

private static class Example正在通过import javafx.application.Application; import static javafx.application.Application.launch; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.scene.Scene; import javafx.scene.control.ListView; import javafx.scene.control.Tab; import javafx.scene.control.TabPane; import javafx.scene.control.TabPane.TabClosingPolicy; import javafx.stage.Stage; /** @see https://stackoverflow.com/a/44102580/230513 */ public class Home extends Application { private TabPane tabpane = new TabPane(); private Example example = new Example(); @Override public void start(Stage primaryStage) { primaryStage.setTitle("Test"); tabpane.setTabClosingPolicy(TabClosingPolicy.UNAVAILABLE); Tab tab = new Tab(); tab.setText("Tab One"); tab.setContent(example.getContent()); tabpane.getTabs().add(tab); Scene scene = new Scene(tabpane); primaryStage.setScene(scene); primaryStage.show(); } private static class Example { ListView<String> view = new ListView<>(); public Example() { ObservableList<String> list = FXCollections.observableArrayList( "Test 1", "Test 2", "Test 3"); view.setItems(list); } public ListView getContent() { return view; } } public static void main(String[] args) { launch(args); } } 方法访问DbSets ...

通用存储库:

Repository

但模拟是通过公开的属性.Set<TEntity>()设置的,而不是//...ctor public Repository(DbContext context) { Context = context; _entities = Context.Set<TEntity>(); //<-- Note method used to access DbSet } //...

<强> HolidayCalendarRepositoryTests

HolidayCalendar

需要将其设置为正在使用的代码的预期行为。

更新设置以包含...

.Set<TEntity>()

...这将允许存储库实现在执行测试时按预期运行。

这里的假设是mockContext .Setup(hc => hc.HolidayCalendar) //<-- Note the setup .Returns(_mockHolidayCalendar.Object); 是某种扩展方法,它将可枚举/可查询的伪数据源分配给模拟集合。