测试存储库方法

时间:2011-01-10 17:28:30

标签: tdd mstest

正如标题所暗示的那样,我正试图测试一种方法,不幸的是我似乎在某些地方出错了。该方法应仅返回具有ID = 1

的客户

这是我的测试

        [TestMethod]
        public void Returns_Correct_Number_Of_Workout_Dates_For_Valid_UserId()
        {

        //Arrange
        List<GymSession> gymSessions = new List<GymSession>();

        Customer cust = new Customer();

        cust.CustomerId = 1;

        gymSessions.Add(new GymSession() { Customer = cust, SessionId = 1, Date = new DateTime(2010, 1, 1)  });
        gymSessions.Add(new GymSession() { Customer = cust, SessionId = 2, Date = new DateTime(2010, 1, 2) });
        gymSessions.Add(new GymSession() { SessionId = 3, Date = new DateTime(2010, 1, 3) });
        gymSessions.Add(new GymSession() { Customer = cust, SessionId = 4, Date = new DateTime(2010, 1, 4) });

        var mockRepos = new Moq.Mock<IGymSessionRepository>();
        mockRepos.Setup(g => g.GymSession()).Returns(gymSessions.AsQueryable());

        //Act
        var result = mockRepos.Object.GetWorkoutDatesByCustomerId(1);

        //Assert
         Assert.AreEqual(3, result.Count());
        }

这是我正在尝试测试的存储库方法

        public IQueryable<GymSession> GetWorkoutDatesByCustomerId(int userId)
    {
        var gymSess = db.GymSessions.Where<GymSession>(g => g.Customer.CustomerId == userId);

        return gymSess;
    }

我们的想法是,安装程序拥有所有客户,然后该方法会对其进行过滤。计数似乎永远不会应用过滤器。有什么想法吗?

1 个答案:

答案 0 :(得分:1)

您似乎确实想要将调用存根到db.GymSessions,并且您应该测试具体的GymSessionRepository实例。传统上,有两种方法可以做到这一点(除了使用面向方面编程拦截调用):

1)为您的存储库提供对db的显式依赖,并在存储库构造函数中要求它。这就是我的意思,我使用IDatabase来表示db

public class GymSessionRepository: IGymSessionRepository {
    private IDatabase db;
    public GymSessionRepository(IDatabase db) {
        this.db = db;
    }
}

// Then in your test ...
var mockDb = new Moq.Mock<IDatabase>();
mockDb.Setup(d => d.GymSessions()).Returns(gymSessions.AsQueryable());

GymSessionRepository repository = new GymSessionRepository(mockDb);
// ... and so on

2)(不太理想,但有时是必要的)将您想要存根的方法公开为虚拟成员,模拟您正在测试的具体对象,并直接在被测试的类上存根行为:

public class GymSessionRepository {
    // Because this is virtual, you can override it in your mock object
    protected virtual List<GymSession> GymSessions() {
        return this.db.GymSessions.AsQueryable();
    }
}

// In your test code here: notice the mock object is your concrete class,
// because your test targets another method on that class, not a method 
// on an arbitrary implementation (like a mock based on its interface)
var mockRepos = new Moq.Mock<GymSessionRepository>();

// Override its virtual method; take control for your test
mockRepos.Setup(g => g.GymSessions()).Returns(gymSessions.AsQueryable());

根据模拟框架,第二种技术称为使用transparentpartial模拟。如果您经常使用它,则可能表明您的代码过度耦合(并且可能会让您感到困惑)。