2013-02-12 21 views
16

không nhất thiết Tôi có một phương pháp mà tôi đang cố gắng gọi từ một bài kiểm tra đơn vị. Phương pháp này trong đời thực sẽ được chạy từ chuỗi nền. Nó sử dụng một số mã để khởi động trong các bản cập nhật gọi đến luồng giao diện người dùng (sử dụng Application.Current.Dispatcher.BeginInvoke ....).Application.Current is null khi gọi từ số

Tuy nhiên Application.Currentnull khi được gọi từ các bài kiểm tra đơn vị.

Tôi không thực sự phải đặt một cái gì đó để sửa lỗi.

Có cách nào khác xung quanh vấn đề này không?

_statusUpdates là một ObservableCollection

Dưới đây là một phần của mã trong phương pháp Tôi đang tìm để kiểm tra (nó là chi tiết của một thử nghiệm tích hợp hơn là một thử nghiệm đơn vị phải công bằng).

Application.Current.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, (EventHandler)delegate 
{ 
    _statusUpdates.Add(new StatusUpdate 
    { 
     DateTime = DateTime.Now, 
     Message = "Checking For Messages" 
    }); 
}, null, null); 
+1

@SonerGonul :-) Bạn sửa tất cả các câu hỏi của con người. Bạn là một người tốt –

+0

Nếu bạn đang làm một bài kiểm tra đơn vị, Ứng dụng đó có bao giờ được khởi tạo không? Thông thường tôi chạy vào một vấn đề như thế này nếu ứng dụng chỉ được khởi động hoặc tắt (và ứng dụng chưa được xây dựng, hoặc đã bị phá hủy). – sircodesalot

+0

@sircodesalot Vâng, đó là vấn đề Application.current là null, khi tôi đang chạy thử nghiệm. Có cách nào tôi có thể buộc nó để nhanh chóng hoặc một cái gì đó, thay vì thêm một tải kiểm tra cho! = Null tất cả các nơi? – DermFrench

Trả lời

9

Như đã nêu, bạn chỉ đơn giản là không có lớp học Application trong khi kiểm tra đơn vị.

Điều đó nói rằng, có một vấn đề ở đây tôi nghĩ nhu cầu giải quyết - bởi có mã mà dựa vào một tài sản tĩnh xác định, trong trường hợp của bạn Application.Current.Dispatch, bây giờ bạn rất chặt chẽ cùng với việc thực hiện cụ thể của lớp đó, cụ thể là được WPF Application lớp học, nơi bạn không cần phải.

Thậm chí nếu bạn chỉ đơn giản quấn ý tưởng "bộ điều phối gốc hiện tại" trong một trình bao bọc lớp kiểu Singleton, bây giờ bạn có một cách để tách riêng mình khỏi những bất thường của lớp Application và xử lý trực tiếp với những gì bạn quan tâm, a Dispatcher:

Lưu ý, có rất nhiều cách để viết điều này, tôi chỉ đang thực hiện triển khai đơn giản nhất có thể; do đó, tôi sẽ không được làm bất kỳ kiểm tra an toàn đa luồng, vv

public class RootDispatcherFetcher 
{ 
    private static Dispatcher _rootDispatcher = null; 

    public static Dispatcher RootDispatcher 
    { 
     get 
     { 
      _rootDispatcher = _rootDispatcher ?? 
       Application.Current != null 
        ? Application.Current.Dispatcher 
        : new Dispatcher(...); 
      return _rootDispatcher; 
     } 
     // unit tests can get access to this via InternalsVisibleTo 
     internal set 
     { 
      _rootDispatcher = value; 
     } 
    } 
} 

Ok, bây giờ thực hiện điều này chỉ hơi tốt hơn so với trước đây, nhưng ít nhất bây giờ bạn có kiểm soát tốt hơn quyền truy cập vào các loại và là không còn phụ thuộc hoàn toàn vào sự tồn tại của phiên bản Application.

+2

Tôi không đồng ý với ý kiến ​​này. Application.Current.Dispatcher sẽ tồn tại bất cứ lúc nào bạn chạy một ứng dụng WPF. Trừ khi bạn viết mã sẽ được sử dụng, nói, trong một cửa hàng ứng dụng Windows vs một ứng dụng Windows Desktop, sau đó không có "khớp nối chặt chẽ". Tôi bạn đang viết mã sẽ được sử dụng cho một ứng dụng WPF, truy cập tài nguyên tĩnh như thế này là hoàn toàn chấp nhận được. – ChrisCW

+0

"Như đã nêu, bạn chỉ đơn giản là sẽ không có một lớp Ứng dụng trong các bài kiểm tra đơn vị." ... Điều đó không đúng. Nếu bạn bắt đầu một ứng dụng (trong một AppDomain riêng), bạn sẽ có một ứng dụng hiện tại trong các bài kiểm tra Unit của bạn. –

+0

Ngoài ra, lý do sử dụng Application.Current.Dispatcher có lẽ là vì bạn cần truy cập vào các phần tử giao diện người dùng, do đó không chỉ bất kỳ điều phối viên nào cũng sẽ làm. – TamaMcGlinn

-1

Vì vậy, vấn đề ở đây là ở đâu đó đối tượng ứng dụng của bạn phải được tạo. Vì vậy, bạn cần phải tìm nơi mà lớp System.Windows.Application (hoặc một số con cháu) đang được khởi tạo.

Nếu dự án được xây dựng từ mẫu, thì có thể bạn sẽ tìm thấy lớp này trong tệp App.xaml. Bạn chỉ cần đảm bảo rằng điều này được khởi tạo bằng cách nào đó. Khác, tìm kiếm toàn bộ dự án của bạn cho một lớp học Application, và sau đó bạn sẽ phải nhanh chóng thực hiện nó theo cách thủ công. Nên sửa chữa nó.

0

Bạn sẽ không có đối tượng Ứng dụng trong Á hậu thử nghiệm đơn vị. Đây thường là các ứng dụng dựa trên "giao diện điều khiển", chỉ cần chạy và thực thi mã không phải giao diện người dùng ("đơn vị").

Tôi khuyên bạn không nên sử dụng khung kiểm tra đơn vị để kiểm tra thông tin cụ thể về giao diện người dùng, tôi đề xuất khung kiểm tra giao diện người dùng tự động để thực hiện điều đó.

7

Đoạn mã sau đây làm việc cho tôi:

if (System.Windows.Application.Current == null) 
    { new System.Windows.Application { ShutdownMode = ShutdownMode.OnExplicitShutdown }; } 

IIRC, tôi đã là một vấn đề mà ứng dụng là vô sử dụng một điều khiển WPF nhúng trong một ứng dụng WinForms và đoạn mã đó đã được đề xuất như một giải pháp cho vấn đề trong một câu hỏi khác trên StackOverflow (xin lỗi, không thể tìm thấy nguồn). Nó giải quyết vấn đề tương tự trong các bài kiểm tra đơn vị (và tôi không tin rằng thuộc tính ShutdownMode cần phải được đặt rõ ràng trong trường hợp đó).

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