简体   繁体   English

使用Moq验证在单独的线程/线程池中发生的方法调用

[英]Verify a method call happening in a separate thread/thread pool using Moq

I have successfully setup and verified methods with Moq before but somehow I can't get this to work. 之前,我已经使用Moq成功设置和验证了方法,但是以某种方式我无法使它起作用。 I tried various answers on the same exception without luck. 我在同一个例外情况下尝试了各种答案,但是没有运气。

I have implemented observer pattern, so I'm mocking IObserver<T> : 我已经实现了观察者模式,所以我在模拟IObserver<T>

var mock = new Mock<IObserver<T>>();
mock.Setup(s => s.OnCompleted());

Here the OnCompleted() looks something like 这里的OnCompleted()看起来像

public void OnCompleted()
{
}

Now in the test, using the mock , I do like this: 现在在测试中,使用mock ,我这样做:

// observable is the SUT.
var unsubscriber = observable.Subscribe(mock.Object);
// Cause OnCompleted() to be called: I verified that there's one observer in the observers list in observable and that my break point is correctly hit.

mock.Verify(v => v.OnCompleted(), Times.AtLeastOnce);
unsubscriber.Dispose(); 

I get the following error: 我收到以下错误:

Message: Moq.MockException : 
Expected invocation on the mock at least once, but was never performed: v => v.OnCompleted()

Configured setups: 
IObserver<T> s => s.OnCompleted()
No invocations performed.

EDIT: SUT Code 编辑:SUT代码

SUT is a class initialized a using a factory method. SUT是使用工厂方法初始化的类。 I will summarize the relevant parts here: 我将在这里总结相关部分:

There's an initializer method: 有一个初始化方法:

public void InitializeMyClass()
{
   for(var i = 0; i < threads.Count; i++)
   {
       Task.Factory.StartNew(() => Proc())
   }

   this.timer = new Timer(CheckStatus, null, 0, 1000);
}

CheckStatus method checks if the workloads in threads started in Initializer reaches a specific status and raises the event indicating completion: CheckStatus方法检查在Initializer中启动的线程中的工作负载是否达到特定状态,并引发指示完成的事件:

private void CheckStatus(object status)
{
   // Inspect all background threads.
   // This is simply done by observing a set of values in a concurrent dict<int, bool>.:

   if (!this.concurrentDict.Values.Any(a => a))
   {
       this.NotifyObservers();
       this.timer.Change(Timeout.Infinite, Timeout.Infinite);
   }
}

NotifyObservers() calls the OnCompleted() method: NotifyObservers()调用OnCompleted()方法:

private void NotifyObservers()
{
    foreach(o in observers)
    {
        o.OnCompleted();
    }
}

This could be a threading issue or the timer might not have invoked by the time the verification was done. 这可能是线程问题,或者在完成验证时可能尚未调用计时器。 Which means that the mock members were not actually called yet when Verify was invoked. 这意味着在调用Verify时尚未真正调用模拟成员。

You might have to wait a bit before verifying method call. 在验证方法调用之前,您可能需要稍等片刻。

Try adding a delay between the Act and Assertion in the test to give the timer enough time to do its thing. 尝试在测试中的“行为”和“断言”之间添加延迟,以使计时器有足够的时间执行其操作。

//Arrange

//...

//Act
// observable is the SUT.
var unsubscriber = observable.Subscribe(mock.Object);
// Cause OnCompleted() to be called: I verified that there's one observer in the observers list in observable and that my break point is correctly hit.

await Task.Delay(TimeSpan.FromSeconds(1.5)); //Or some known duration

//Assert    
mock.Verify(v => v.OnCompleted(), Times.AtLeastOnce);
unsubscriber.Dispose(); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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