2012-10-17 17 views
6

Tôi có một cấu trúc ví dụ .:Tạo một cấu trúc với autofixture ném không có lỗi constructor nào

public struct Foo 
{ 
    public int Bar; 
    public string Baz; 
} 

và muốn tạo ra nó trong các bài kiểm tra đơn vị của tôi sử dụng autofixture. Tôi đã thử sử dụng các mục sau:

IFixture fixture = new Fixture(); 
var f = fixture.CreateAnonymous<Foo>(); 

Nhưng điều này sẽ gây ra lỗi AutoFixture was unable to create an instance. Có thể tự động tạo ra một cấu trúc với autofixture? Làm thế nào điều này có thể được thực hiện? Xin lưu ý rằng tôi đang làm việc trên mã cũ và do đó cần phải xử lý các cấu trúc. :)

EDIT:

Changed

IFixture fixture = new Fixture().Customize(new AutoMoqCustomization()); 

Để

IFixture fixture = new Fixture(); 

Vì nó không phải là thích hợp cho câu hỏi này.

+0

Nếu bạn gỡ bỏ tùy chỉnh AutoMoq, nó có khác biệt không? –

+0

Nó không tạo ra bất kỳ sự khác biệt nào. – Rok

+1

Cool - đưa nó ra khỏi câu hỏi và @Peter Porfy có thể loại bỏ đầu cơ của mình ... –

Trả lời

8

Đây thực chất là một vật phẩm về cách trình biên dịch C# xử lý các loại giá trị. Trong khi the documentation seems to indicate otherwise, từ quan điểm của Reflection, cấu trúc Foo không có các hàm tạo công khai nào.

Ví dụ: nếu bạn thực thi mã này:

var ctors = typeof(Foo).GetConstructors(); 

kết quả là một mảng trống.

Tuy nhiên, mã này biên dịch:

var f = new Foo(); 

vì vậy bạn có thể tranh luận rằng AutoFixture sẽ có thể tạo ra một thể hiện của Foo.

Tuy nhiên, cuối cùng, mutable structs are evil và phải tránh bằng mọi giá. Một lựa chọn tốt hơn là thay đổi việc thực hiện Foo này:

public struct Foo 
{ 
    public Foo(int bar, string baz) 
    { 
     this.Bar = bar; 
     this.Baz = baz; 
    } 

    public readonly int Bar; 
    public readonly string Baz; 
} 

Nếu bạn làm điều này, không chỉ làm bạn bây giờ có một (nhiều) đúng kiểu giá trị, nhưng AutoFixture cũng có thể tạo ra một thể hiện mà không sửa đổi thêm .

Vì vậy, đây là ví dụ khá hay về mô hình GOOS mà bạn nên nghe thử nghiệm của mình. Nếu chúng có ma sát, nó có thể là phản hồi về mã sản xuất của bạn. Trong trường hợp này, đây là phản hồi chính xác rằng bạn sắp tự bắn mình vào chân vì việc triển khai loại giá trị là thiếu sót.

P.S. Thậm chí nếu bạn 'sửa' cấu trúc Foo như được nêu ở trên, thì làm thế nào để tạo ra cấu trúc thay vì một lớp? Nó vẫn chứa một chuỗi (các kiểu tham chiếu) trường, vì vậy mặc dù cấu trúc chính nó sẽ sống trên ngăn xếp, trường chuỗi vẫn sẽ trỏ đến dữ liệu trong heap.


Tôi đã thêm this issue làm tính năng mới có thể có cho AutoFixture.

+0

Cảm ơn bạn cho câu trả lời đầy đủ! Tôi sẽ thêm các nhà thầu để cấu trúc, vì điều này sẽ không ảnh hưởng đến mã cũ, nhưng vì lý do tương tự, tôi không thể làm cho chúng trở nên bất biến. Đối với các cấu trúc, chúng được sử dụng như mã DTO mã kế thừa. Vì trong các lớp ý kiến ​​của tôi phù hợp hơn với công việc, tôi cố gắng tái cấu trúc một phần của mã để sử dụng các lớp thay thế. Nhưng vì các cấu trúc vẫn sẽ được sử dụng bởi các phần khác của mã, tôi cần kiểm tra chuyển đổi giữa chúng và các lớp thay thế. Tôi hy vọng tôi làm một trường hợp sử dụng với điều này. :) Ngoài ra xin vui lòng gửi lại, nếu tính năng được thực hiện! – Rok

1

Với sự gợi ý từ blog post này, tôi tạo ra một lớp mà thực hiện các ISpecimenBuilder

class FooBuilder : ISpecimenBuilder 
{ 
    public object Create(object request, ISpecimenContext context) 
    { 
    var sr = request as SeededRequest; 
    if (sr == null) 
    { 
     return new NoSpecimen(request); 
    } 
    if (sr.Request != typeof(Foo)) 
    { 
     return new NoSpecimen(request); 
    } 

    var foo = new Foo(); 
    foo.Bar = context.CreateAnonymous<int>(); 
    foo.Baz = context.CreateAnonymous<string>(); 
    return foo; 
    } 
} 

Và thêm lớp như tùy biến

fixture.Customizations.Add(new FooBuilder()); 

gây ra cuộc gọi đến CreateAnonymous<Foo> để làm việc.

Nếu có thêm giải pháp hộp, vui lòng đăng và tôi sẽ chấp nhận câu trả lời.

+0

+1 Bạn có thể sử dụng 'AutoPropertiesCommand 'như được hiển thị trong [thảo luận này] (http://autofixture.codeplex.com/discussions/222358) để tự động chuyển nhượng - –

+0

@anonympous Downvoter. Bất kỳ lý do nào bạn muốn chia sẻ? Trong trường hợp không có giải pháp tốt hơn, đây là một công việc (và tôi dám nói nó al # thành ngữ nhất về thực tế là nó móc các đường ống theo cách chính xác) workaround (esp với generalisation khác) –

Các vấn đề liên quan