Тестирование репозитория - PullRequest
0 голосов
/ 10 января 2011

Как видно из названия, я пытаюсь протестировать метод, но, к сожалению, где-то я ошибаюсь. Метод должен возвращать только тех клиентов, которые имеют и 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 Ответ

1 голос
/ 10 января 2011

Похоже, что вы действительно хотите заблокировать вызов 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());

В зависимости от структуры насмешек, второй метод известен как использование прозрачного или частичный макет.Если вы обнаружите, что используете его часто, это может быть признаком того, что ваш код чрезмерно связан (и это может быстро запутать).

...