2010-07-02 37 views
6

Tôi có một hạng A trong đó có những điều sau đây:Moq nhập khẩu MEF?

public class A { 
    [Import(typeof(IMyService)] 
    public IMyService MyService { get; set; } 

    public A() { 
     CompositionInitializer.SatisfyImports(this); 
    } 

    public void DoWork() { 
     //Blah 
     MyService.DoIt(); 
     //Blah 
    } 
} 

Và một thử nghiệm để kiểm tra này (riêng biệt DLL - rõ ràng)

[TestMethod] 
public void TestDoWork() { 
    //Blah 
    DoWork(); 
    //Assert assert 
} 

này không như cố gắng gọi 'MyService' mang lại cho tôi vô . Tôi đã cố gắng sau đó:

[ClassInitialize] 
public void InitialiseClass() { 
    var myService = new Mock<IMyService>(); 
    MyService = myService.Object; 
} 

với 'MyService' khai báo là:

[Export(typeof(IMyService))] 
public IMyService MyService { get; set; } 

Nhưng vẫn không có niềm vui, tôi thiếu một cái gì đó - là điều này thậm chí có thể?

Tôi đang sử dụng SL3, MEF Preview 9 và MOQ.

Bất kỳ trợ giúp nào được đánh giá cao!

Cheers

Chris

Trả lời

4

lớp của bạn sẽ trông như thế này:

public class A 
{ 
    private readonly IMyService _myService; 

    [ImportingConstructor] 
    public A(IMyService myService) 
    { 
     _myService = myService; 
    } 

    public void DoWork() { 
     //Blah 
     _myService.DoIt(); 
     //Blah 
    } 
} 

Và thử nghiệm của bạn sẽ trông như thế này:

[TestMethod] 
public void DoWork_invokes_IMyService_DoIt() 
{ 
    // arrange mock and system under test 
    var myService = new Mock<IMyService>(); 
    var a = new A(myService.Object); 

    // act  
    a.DoWork(); 

    // assert that DoIt() was invoked 
    myService.Verify(x => x.DoIt()); 
} 

Thực tế là bạn sử dụng MEF không nên quan trọng trong việc kiểm tra đơn vị. MEF chỉ phát huy tác dụng khi kết nối nhiều thành phần với nhau, điều này hoàn toàn ngược lại với những gì xảy ra trong một thử nghiệm đơn vị. Một thử nghiệm đơn vị là định nghĩa một thử nghiệm của một thành phần trong sự cô lập.

Sửa: nếu bạn thích tiêm bất động sản, sau đó lớp học của bạn không cần một constructor và phần sắp xếp trong thử nghiệm đơn vị của bạn sẽ trông như thế thay vì điều này:

var myService = new Mock<IMyService>(); 
    var a = new A(); 
    a.MyService = myService.Object; 
+0

OK, nhưng tại sao tôi cần phải sử dụng nhà nhập khẩu hàm xây dựng, thuộc tính đang hoạt động tốt trong triển khai thực tế của tôi, có lẽ có một tuyến đường để có thể giả lập các loại nhập đó? –

+1

@Chris: mặc dù MEF khuyến khích tiêm tài sản, tôi thích tiêm xây dựng vì cách đó trình biên dịch ngăn bạn tạo đối tượng bị thiếu phụ thuộc. Nó cũng cho phép bạn làm cho các trường phụ thuộc chỉ đọc, vì vậy bạn không phải suy nghĩ về những gì sẽ xảy ra nếu một sự phụ thuộc được thay thế. –

+0

Tôi đã chọn phương pháp này, cá nhân tôi vẫn muốn biết liệu bạn có thể giả định việc tiêm tài sản hay không, nhưng điều này giúp khắc phục sự cố tôi gặp phải. Chúc mừng. –

1

Trong trường hợp bạn đã thêm [Xuất khẩu] để dụ IMyService của bạn, bạn đã thực sự nói thêm rằng để container thành phần? Nếu không, nó sẽ không tham gia vào sáng tác. Để thêm một đối tượng chế giễu để container, làm như sau:

container.ComposeExportedValue<IMyService>(mock.Object); 

Hoặc chỉ:

container.ComposeExportedValue(mock.Object); // type inference. 

Việc làm này trước khi bạn đã tạo một thể hiện của A sẽ cho phép nó được cấu tạo bên trong của bạn Một ví dụ.

+0

Tôi không cần phải thêm việc thực hiện cụ thể để một container để làm cho nó làm việc. Nhưng tôi thấy quan điểm của bạn. Bạn đang xem vùng chứa ở đâu? –

0

Bạn không nên sa thải lập MEF trong các bài kiểm tra đơn vị của bạn. Thành phần là cách vượt quá phạm vi của đơn vị thử nghiệm, không khác với một container IoC.

phụ thuộc insted, bạn nên tiêm cần thiết bằng tay:

[TestClass] 
public class ATest { 
    Mock<IMyService> myService ; 
    [TestInitialize] 
    public void InitialiseClass() { 
    myService = new Mock<IMyService>(); 
    } 

    [TestMethod] 
    public void DoWorkShouldCallDoIt { 
    A a = new A(); 
    a.MyService = myService.Object; 
    a.DoWork(); 
    myService.Verify(m=>m.DoIt(), Times.Once()); 
    } 
}