2010-09-01 23 views
7

Tôi đang cố gắng để tạo ra bối cảnh giả accodring để http://blogs.msdn.com/b/adonet/archive/2009/12/17/walkthrough-test-driven-development-with-the-entity-framework-4-0.aspxKiểm tra EF 4.0 với các mẫu POCO và t4 - Ngữ cảnh mô phỏng như thế nào?

Như tôi có thể nhìn thấy ở đó là một giao diện mà thấy nhiều phương pháp mà trả IObjectSet < ...>, nhưng T4 mẫu tạo ra phương pháp mà trả ObjectSet < ...> và không có giao diện được tạo ra và trên trang đó tác giả thêm giao diện để tạo bối cảnh và nó cho anh ta cách để tạo mô hình, vv

Mục tiêu chính của tôi là sử dụng mẫu T4 để tạo lớp poco và tạo ngữ cảnh giả/giả để kiểm tra kho lưu trữ tùy chỉnh của tôi. Có cách nào để làm cho nó hoạt động mà không cần viết hoặc thay đổi mẫu T4 ?? Làm thế nào tôi có thể tạo mocks trên bối cảnh (đối với IObjectSet is't tầm thường) nếu nó trở ObjectSet thay vì IObjectSets ...

Thx trước

Trả lời

3

Tác giả chỉ là chế giễu kho, không phải là thực thể. EntityFramework tạo ra các ObjectQueries, nhưng anh ta kết thúc chúng và kho lưu trữ của nó trả về các câu hỏi IObjectQueries. Anh ta làm điều này để anh ta có thể dễ dàng giả lập dữ liệu, sau đó trong quá trình cứu anh ta chỉ xác thực các thực thể.

Nếu bạn chỉ đang cố gắng tạo kho lưu trữ "giả", bạn có thể tạo mẫu T4 của riêng mình và lặp lại qua tệp edmx và tạo mã. Nhưng không có lý do gì để tạo ra POCOS? Chúng đã tồn tại, tại sao bạn cần tạo lại chúng? Ông tóm tắt tất cả mọi thứ thành một "chung chung" FakeObjectSet do đó, thực sự không có nhiều mã để viết?

Bạn có cố gắng để tạo ra điều này:

public IObjectSet<Blog> Blogs 
    { 
     get 
     { 
      return _blogs ?? (_blogs = new FakeObjectSet<Blog>()); 
     } 
     set 
     { 
      _blogs = value as FakeObjectSet<Blog>; 
     } 
    } 
    private FakeObjectSet<Blog> _blogs; 

Nếu vậy tôi sẽ đoán bạn sẽ dành nhiều thời gian với T4 sau đó bạn sẽ chỉ viết nó.


Ví dụ T4 mà không cần khai báo lớp ... bạn có thể làm t4 hoàn chỉnh bằng cách làm theo this blog

<# 
    foreach (EntitySet set in container.BaseEntitySets.OfType<EntitySet>()) 
    { 
#> 
public IObjectSet<<#=MultiSchemaEscape(set.ElementType, code)#>> 
{ 
    get{ 
     return <#=code.FieldName(set)#> ?? (<#=code.FieldName(set)#> = FakeObjectSet<<#=MultiSchemaEscape(set.ElementType, code)#>>("<#=set.Name#>")); 
    } 
    set{ 
    <#=code.FieldName(set)#> = value as FakeObjectSet<<#=MultiSchemaEscape(set.ElementType, code)#>>("<#=set.Name#>"); 
    } 
} 
private FakeObjectSet<<#=MultiSchemaEscape(set.ElementType, code)#>> <#=code.FieldName(set)#>; 
<# 
} 

#> 

Trong đó sẽ tạo ra mã này:

public IObjectSet<Blogs>{ 
    get{ 
    return _Blogs?? (_Blogs = FakeObjectSet<Blog>("Blogs")); 
    } 
    set{ 
    _Blogs= value as FakeObjectSet<Class>("Blogs"); 
    } 
} 

private FakeObjectSet<Blog> _Blogs; 

Side lưu ý .

IObjectSet được chứa trong System.Data để Thêm một tham chiếu đến System.Data.Entity.dll

+0

Mayby Tôi đã bỏ lỡ hiểu, tôi chỉ dựa trên bài viết này. Tôi biết rằng tác giả có các lớp POCOS, nhưng tôi có DB lớn, đã có, tôi phải tạo edmx từ DB này và tiếp theo sau nhiều difficoulties (đây là Oracle DB), tôi có thể sử dụng các mẫu T4 để tạo các lớp POCO, bởi vì tôi không viết chúng trước bằng tay. Bây giờ tôi muốn thêm bài kiểm tra đơn vị và tôi phải thử đối tượng bối cảnh của tôi nếu tôi muốn kiểm tra kho. Vì vậy, T4 đã tạo các lớp POCO cho các thực thể và lớp cho Ngữ cảnh, nhưng thiếu giao diện cho ngữ cảnh này nên tôi không thể tạo mô hình dựa trên giao diện này. – Simon

+1

Nhờ http://slappyza.wordpress.com/2010/08/08/getting-the-entity-framework-to-generate-an-interface-for-mocking/ Tôi đã giải quyết sự cố ngay bây giờ .. . :) – Simon

+0

+1. Thực sự, tất cả những gì cần phải xảy ra là thêm 'I' vào các khai báo' ObjectSet ... 'hiện có ... –

1

Trích trong The Art Of Unit Testing bởi Roy Osherove:

Không có vấn đề hướng đối tượng mà không thể được giải quyết bằng cách thêm một lớp indirection, ngoại trừ, tất nhiên, quá nhiều lớp indirection.

Dưới đây là thiết lập PIXO EF4 giả của tôi. Tôi đã không sử dụng T4 vì nó quá khó để làm việc ra làm thế nào để làm sạch các mẫu để không tạo ra quá nhiều gumpf. Bạn có thể tất nhiên hack mẫu T4 để nhổ ra một cái gì đó giống như cấu trúc này.

Bí quyết là tạo ObjectSet<T> s theo cách thủ công và hiển thị chúng dưới dạng IQueryable.Vì AddCreate là trên ObjectSet<T>/ObjectSet<T>, tôi cũng phải thêm các phương thức để thêm và tạo các thực thể.

public interface IStackTagzContext { 
    IQueryable<Question> Questions { get; } 

    Question CreateQuestion(); 

    void CreateQuestion(Question question); 

    void SaveChanges(); 
} 

public class StackTagzContext : ObjectContext, IStackTagzContext { 
    public StackTagzContext() : base("name=myEntities", "myEntities") 
    { 
     base.ContextOptions.LazyLoadingEnabled = true; 
     m_Questions = CreateObjectSet<Question>(); 
    } 

    #region IStackTagzContext Members 
    private ObjectSet<Question> m_Questions; 
    public IQueryable<Question> Questions { 
     get { return m_Questions; } 
    } 


    public Question CreateQuestion() { 
     return m_Questions.CreateObject(); 
    } 
    public void AddQuestion(Question question) { 
     m_Questions.AddeObject(question); 
    } 

    public new void SaveChanges() { 
     base.SaveChanges(); 
    } 

    #endregion 
} 

Bây giờ, bạn sẽ lưu ý rằng loại bộ sưu tập thực thể trên giao diện là IQueryable<T>, như trái ngược với IObjectSet<T>. Tôi không thể làm phiền việc tạo FakeObjectSetIQueryable đã cung cấp cho tôi đủ linh hoạt. Vì vậy, để KISS, tôi đã quản lý mà không có nó.

Mocking IQueryable, mặt khác, là tầm thường:

using Moq; 
[TestClass] 
public class TestClass { 

    Mock<IStackTagzContext> m_EntitiesMock = new Mock<IStackTagzContext>(); 


    [TestMethod()] 
    public void GetShouldFilterBySite() { 
     QuestionsRepository target = new QuestionsRepository(m_EntitiesMock.Object); 

     m_EntitiesMock.Setup(e=>e.Questions).Returns(new [] { 
     new Question{Site = "site1", QuestionId = 1, Date = new DateTime(2010, 06,23)}, 
     }.AsQueryable()); 
    } 
} 
Các vấn đề liên quan