Я бы хотел проверить какой-то код, и для этого мне нужно подделать DbContext, определенный в DAL ( Entity Framework 6 - Code first
). Это происходит в основном хорошо, но я столкнулся с проблемой, когда класс модели данных использует атрибут TypeName
. Я сделал скелет, чтобы продемонстрировать эту проблему.
Модель данных:
[Table("Customer")]
public class Customer
{
[Key]
public int Id { get; set; }
public string FirstName{ get; set; }
public string LastName { get; set; }
//this line causes the exception
[Column(TypeName = "money")]
public decimal Salary { get; set; }
}
Определение контекста
public class MyDbContext : DbContext
{
public MyDbContext(string nameOrConnectionString) : base(nameOrConnectionString)
{
}
public MyDbContext(DbConnection connection) : base(connection, true)
{
}
public IDbSet<Customer> Customers { get; set; }
}
И фиктивный метод для создания фальшивого контекста с некоторыми данными:
private MyDbContext GenerateFakeDbContext()
{
var connection = DbConnectionFactory.CreateTransient();
var context = new MyDbContext(connection);
var customer = new Customer
{
Id = 1,
FirstName = "X",
LastName = "Y",
Salary = 1000
};
//this line throws the exception
context.Customers.Add(customer);
return context;
}
Проблема заключается в атрибуте TypeName
. Когда он закомментирован, тесты проходят. Но если это включено, я получил System.InvalidOperationException
, сказав:
Последовательность не содержит соответствующего элемента
Подводя итог, я задаю следующие вопросы:
Я бы посоветовал вам взглянуть на EntityTypeConfigurations и переместить ваши сопоставления там: http://www.entityframeworktutorial.net/code-first/entitytypeconfiguration-class.aspx
Это позволит вам не учитывать вашу текущую БД и проверять свои сущности / интерфейсы, используя их, не принимая во внимание Entity Framework.
Мне также кажется, что вы выполняете интеграционное тестирование вместо модульного тестирования. Чтобы выполнить модульное тестирование, вы должны избавиться от реального использования DbContext (ваша текущая реализация использует конкретную реализацию EF для DAL, но вместо этого должна использоваться абстракция).
Я бы рекомендовал по крайней мере обернуть свой DbContext в интерфейсе, чтобы вы могли высмеивать его / заглушить его лучше:
public interface IDbContext {
IDbSet<Customer> Customers { get; set; }
}