2015-07-10 1 views
2

у меня есть это в моем тестовом сценарии:установка Moq не возвращает значение в то время как сказал

var dbConnection = new Mock<IDbConnection>(); 
dbConnection.Setup(x => x.SearchFor<User>("users", y => y.Password =="12345" 
    && y.Username == "tester")).Returns(new List<User>{ 
     new User{ 
      Username = "tester", 
      Password = "12345" 
     }}.AsQueryable()); 

var users = new Users.Users(dbConnection.Object); 
var user = users.Get("tester", "12345"); 

При взгляде на Получ:

public User Get(string username, string password){ 
    var total = _dbConnection.SearchFor<User>("users", y => 
     y.Password == password && 
     y.Username == username).Single(); 
    return total; 
} 

Он должен работать в соответствии большинство образцов I найти в Интернете, но он всегда дает мне:

System.InvalidOperationException: Sequence contains no elements 

Когда я изменить Получ к этому:

public User Get(string username, string password){ 
    var total = _dbConnection.SearchFor<User>("users", y => 
     y.Password == "12345" && 
     y.Username == "tester").Single(); 
    return total; 
} 

Это magicaly работает, но метод get находится в бизнес-слое и, как мы все знаем ..., чтобы установить имя пользователя и пароль hardcoded, никогда не бывает хорошим.

Вопрос: Как я могу правильно настроить настройку для moq? Что я делаю не так?

ответ

1

так что вы настраиваете, ожидая параметров "users" и y => y.Password == "12345" && y.UserName == "tester". Однако ваш второй параметр - лямбда, которые трудно сравнивать (если не невозможно?). Итак, когда Moq проверяет, не вызвал ли вы это, он в конечном счете пытается сравнить lambdas, который, вероятно, потерпит неудачу.

Например, следующий код показывает два, казалось бы, идентичные функции, но они не считаются равными:

Func<bool> a =() => true; 
Func<bool> b =() => true; 
(a == b).Dump(); //False 
a.Equals(b).Dump(); //False 

Поэтому Moq не знает, использовать возвращаемое значение, что вы настройки.

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

Что-то вроде этого:

class TestRepo 
{ 
    public void Add<T>(T myType) 
    { 
     //add to an in-memory "database" 
    } 
    public IEnumerable<T> Get<T>(Expression<Func<T, bool>> filter) 
    { 
     return inMemoryDataBase.Where(filter); 
    } 
} 

Что бы сделать свой Get метод выглядеть примерно так:

public User Get(string username, string password){ 
    var total = RealRepo.Get<User>(y => 
     y.Password == "12345" && 
     y.Username == "tester").Single(); 
    return total; 
} 

И тест:

var repo = new TestRepo(); 
repo.Add(new User { Username = "tester", Password = "12345" }); 
var users = new Users.Users(dbConnection.Object); 
var user = users.Get("tester", "12345"); 

Вот несколько связан вопрос где пользователь пытался найти способ однозначно идентифицировать лямбда, так что на них можно «сравнить» так, как вы надеетесь. Я не знаю, что там были найдены идеальные решения. Link