简体   繁体   中英

Testing with MEF and Moq and NUnit

Shown below are the class and the method in the test class. The test method is for testing during the state that a monitoring request is published. The expected action is that the handler is called inside the FzrteMonitoringService class.

Here, I am trying to verify whether the handler for the monitoringRequestGenerated event is called inside the FzrteMonitoringService class. But the problem is that the class Dependency is a dependency, and I trying to figure out how to write the FzrteMonitoringService class to avoid such a dependency. The Dependency class is a class that works with MEF to resolve instances exported with the Export attribute. An architect was responsible for its design. Replacing the Dependency class with a TestDependency class for tests seems like an idea, but how would it create instances?

        [ImportingConstructor]
        public FzrteMonitoringService(IEventAggregator inEventAggregator)
        {
            _eventAggregator = inEventAggregator;
            _monitoringRequestExecutor = Dependency.Resolve<IFzrteMonitoringRequestResponseHandler>();
            WatchedPorts = new List<string>();
            FailedAddWatchRequests = new List<MonitoringRequest>();
            _monitoringRequests = new ConcurrentQueue<FzrteMonitoringRequest>();

            //subsription for monitoring requests on the UI thread to limit the user
            //from generating meaningless requests
            _eventAggregator.GetEvent<MonitoringRequestGenerated>()
                .Subscribe(FilterEventType, ThreadOption.UIThread, true);

        }

        [Test]
        [Category("Simple Basic Tests")]
        public void SubscribesToMonitoringRequets_requestPublished_FilterEventTypeCalled()
        {
            //mock of event aggregator and the request event dependencies of monitoring service
            var mockEventAggregator = new Mock<IEventAggregator>();
            var mockMonitoringRequestedEvent = new Mock<MonitoringRequestGenerated>();

            mockEventAggregator.Setup(x => x.GetEvent<MonitoringRequestGenerated>())
                .Returns(mockMonitoringRequestedEvent.Object);

            Action <List<MonitoringRequest>> callbackMethod = null;

            mockMonitoringRequestedEvent.Setup(x => x.Subscribe(
                It.IsAny<Action<List<MonitoringRequest>>>(),
                It.IsAny<ThreadOption>(),
                It.IsAny<bool>(),
                It.IsAny<Predicate<List<MonitoringRequest>>>())).
                Callback<Action<List<MonitoringRequest>>,
                    ThreadOption,
                    bool,
                    Predicate<List<MonitoringRequest>>>((a, t, b, p) => callbackMethod = a);



            var testFzrteMonitoringService = new FzrteMonitoringService(mockEventAggregator.Object);

            //use the actual  event aggregator to publish

            var mockMonitoringRequestEventPayload = new Mock<List<MonitoringRequest>>();
            mockEventAggregator.Object.GetEvent<MonitoringRequestGenerated>().Publish(mockMonitoringRequestEventPayload.Object);

            mockMonitoringRequestedEvent.Verify(x => x.Subscribe(testFzrteMonitoringService.FilterEventType));


        }

It's not really clear what exactly you're trying to test, looking on a code you've provided, but I'll try to address your question.

The main problem with Dependency class is that it's static (or probably its Resolve<> method). You should try to abstract it via introducing IDependency interface

public interface IDependency
{
    T Resolve<T>();
}

so you can inject it into your service and then mock it in your tests. After this simple refactoring your service's constructor will look like this:

[ImportingConstructor]
public FzrteMonitoringService(
        IEventAggregator inEventAggregator, 
        IDependency dependency)
{
    _eventAggregator = inEventAggregator;
    _dependency = dependency;

    _monitoringRequestExecutor = dependency.Resolve<IFzrteMonitoringRequestResponseHandler>();
    WatchedPorts = new List<string>();
    _monitoringRequests = new ConcurrentQueue<FzrteMonitoringRequest>();

    //subsription for monitoring requests on the UI thread to limit the user
    //from generating meaningless requests
    _eventAggregator.GetEvent<MonitoringRequestGenerated>()
        .Subscribe(this.FilterEventType, ThreadOption.UIThread, true);
}

and your test:

[Test]
[Category("Simple Basic Tests")]
public void SubscribesToMonitoringRequets_requestPublished_FilterEventTypeCalled()
{
    //mock of event aggregator and the request event dependencies of monitoring service
    var mockEventAggregator = new Mock<IEventAggregator>();
    var mockMonitoringRequestedEvent = new Mock<MonitoringRequestGenerated>();
    var mockDependecy = new Mock<IDependency>();

    mockEventAggregator.Setup(x => x.GetEvent<MonitoringRequestGenerated>())
            .Returns(mockMonitoringRequestedEvent.Object);

    Action<List<MonitoringRequest>> callbackMethod = null;

    mockMonitoringRequestedEvent
            .Setup(
                x => x.Subscribe(
                    It.IsAny<Action<List<MonitoringRequest>>>(),
                    It.IsAny<ThreadOption>(),
                    It.IsAny<bool>(),
                    It.IsAny<Predicate<List<MonitoringRequest>>>()))
            .Callback<Action<List<MonitoringRequest>>, ThreadOption, bool, Predicate<List<MonitoringRequest>>>(
                (a, t, b, p) => callbackMethod = a);

    var testFzrteMonitoringService = new FzrteMonitoringService(
            mockEventAggregator.Object, mockDependecy.Object);

    //use the actual  event aggregator to publish

    var mockMonitoringRequestEventPayload = new Mock<List<MonitoringRequest>>();
    mockEventAggregator.Object
            .GetEvent<MonitoringRequestGenerated>()
            .Publish(mockMonitoringRequestEventPayload.Object);

    mockMonitoringRequestedEvent.Verify(
            x => x.Subscribe(testFzrteMonitoringService.FilterEventType));
}

Though it may not work properly, but the main idea is there.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM