C# Resharper测试运行程序未输出Console.WriteLine()?
为什么从控制台应用程序C# Resharper测试运行程序未输出Console.WriteLine()?,c#,unit-testing,resharper,C#,Unit Testing,Resharper,为什么从控制台应用程序main()方法执行时,Console.Writeline()会起作用;但是当我使用resharpers测试运行程序执行相同的测试时,我在测试运行程序输出窗口中没有看到控制台.Writeline() 最好的解释方法是用一个例子 我使用的是:Resharper Ultimate 2017.1.3、Visual Studio 2017社区和.Net 4.6.1框架。语言是C#。我还(通过nuget)安装了nunit framework 2.6.4 首先创建一个类库,并将以下内容
main()
方法执行时,Console.Writeline()
会起作用;但是当我使用resharpers测试运行程序执行相同的测试时,我在测试运行程序输出窗口中没有看到控制台.Writeline()
最好的解释方法是用一个例子
我使用的是:Resharper Ultimate 2017.1.3、Visual Studio 2017社区和.Net 4.6.1框架。语言是C#。我还(通过nuget)安装了nunit framework 2.6.4
首先创建一个类库,并将以下内容复制粘贴到.cs文件中
using System;
using System.Collections;
using System.Threading;
using NUnit.Framework;
namespace ObserverPatternExample
{
[TestFixture]
internal class ObserverTestFixture
{
[Test]
public void DemonstrateObserverPattern()
{
var subject = new Subject();
var a = new Observer(subject, "a");
var b = new Observer(subject, "b"); // etc. as many observers as you want.
subject.Go();
}
}
// "subject" is observer pattern lingo. The "subject" will do the broadcasting to the observers.
public class Subject
{
public delegate void CallbackHandler(string s);
public event CallbackHandler NotifyEvent;
private const int waitTimeInMilliseconds = 200;
private readonly Simulator simulator = new Simulator();
public string FakeSimulatorState { get; set; }
public void Go()
{
new Thread(Run).Start(); // a good thing to notice: events cross thread boundaries!!!
}
private void Run()
{
foreach (string s in simulator)
{
Console.WriteLine("Subject: " + s);
FakeSimulatorState = s;
NotifyEvent?.Invoke(s);
Thread.Sleep(
waitTimeInMilliseconds); // we do this to "pretend" that the simulator is actually doing someting.
}
}
}
public class Observer : IObserverPattern // the "observer" will subscribe to the event being broadcast by the "subject"
{
private readonly string _name;
public Observer(Subject subject, string name)
{
_name = name;
subject.NotifyEvent += Update;
}
public void Update(string state)
{
Console.WriteLine("Observer {0}: {1}", _name, state);
}
}
internal interface IObserverPattern
{
void Update(string state);
}
public class Simulator : IEnumerable
{
private readonly string[] _stateSequence = { "BEGIN", "CRAWL", "WALK", "JUMP", "END" };
public IEnumerator GetEnumerator()
{
foreach (var s in _stateSequence)
yield return s;
}
}
}
现在执行测试。我希望看到Console.WriteLine()调用在Resharper测试运行程序输出窗口中显示字符串。但我没有。例如,下面是一个屏幕截图:
现在让我们执行完全相同的序列,但这次我们将从一个新的控制台项目main()方法调用客户机代码。要设置此副本,请粘贴以下代码并引用在上述步骤中创建的类库
using ObserverPatternExample;
namespace ConsoleApp1
{
internal class Program
{
private static void Main(string[] args)
{
var subject = new Subject();
var a = new Observer(subject, "a");
var b = new Observer(subject, "b"); // etc. as many observers as you want.
subject.Go();
}
}
}
接下来执行控制台应用程序。您应该会看到显示以下内容:
有人能解释一下我如何配置代码或测试运行程序以在测试运行程序输出窗口中显示输出吗
*更新*
我取得了部分成功。中间人建议使用TraceListener
使我意识到我应该使用ConsoleTraceListener
。为了简化这一点,我修改了单元测试,如下所示:
using System.Threading;
using NUnit.Framework;
namespace ObserverPatternExample.DontUse
{
[TestFixture]
internal class ObserverTestFixture
{
[SetUp]
public void Setup()
{
Trace.Listeners.Add(new ConsoleTraceListener());
}
[TearDown]
public void TearDown()
{
Trace.Flush();
}
[Test]
public void DemonstrateObserverPattern()
{
var subject = new Subject();
var a = new Observer(subject, "a");
var b = new Observer(subject, "b"); // etc. as many observers as you want.
subject.Go();
}
}
结果令人惊讶:我确实得到了一些输出;但只有初始的开始状态。看起来是这样的:
using System.Threading;
using NUnit.Framework;
namespace ObserverPatternExample.DontUse
{
[TestFixture]
internal class ObserverTestFixture
{
[SetUp]
public void Setup()
{
Trace.Listeners.Add(new ConsoleTraceListener());
}
[TearDown]
public void TearDown()
{
Trace.Flush();
}
[Test]
public void DemonstrateObserverPattern()
{
var subject = new Subject();
var a = new Observer(subject, "a");
var b = new Observer(subject, "b"); // etc. as many observers as you want.
subject.Go();
}
}
小故事:我仍在寻找解决方案
***解决方案****
[Test]
public void DemonstrateObserverPattern()
{
var subject = new Subject();
var a = new Observer(subject, "a");
var b = new Observer(subject, "b"); // etc. as many observers as you want.
subject.Go();
Thread.Sleep(1000); // <--- add this to force test runner to wait for other thread to complete.
}
[测试]
public void DemonstrateObserverPattern()演示
{
var subject=新的subject();
var a=新观察者(主体“a”);
var b=新的观察者(subject,“b”);//等等。尽可能多的观察者。
subject.Go();
Thread.Sleep(1000);//看起来Resharper在线程完成之前就完成了。您对
Thread(Run).Start();
这意味着测试线程将在Go线程完成之前完成,因此不会得到任何结果
请参阅where is states“注意,对Start的调用不会阻止调用线程。”将信息输出到用户界面是否违背了单元测试的目的?是什么使测试成功或失败,以及输出到控制台的内容如何在该决定中发挥作用?如果是出于调试目的,则应使用System.Diagnostics.Debug
和您选择的TraceListener
。@InBetween:我正在为一位同事设置这个示例,他的工作是编写单元测试断言方法。在输出窗口中编写一些有用的控制台.writeline()没有什么错。它可以帮助我的同事“一目了然”地看到状态。谢谢。这就成功了。在我的单元测试中,我添加了Thread.Sleep(1000);并且能够看到输出。此外,不需要TraceListener等。我能够使用Console.WriteLine()和Thread.Sleep()实现所需的结果,仅此而已。做得好,尽管我鼓励您避免在测试中睡觉,因为这会增加不必要的延迟,并引入您所经历的比赛条件。在这种情况下,更好的选择是使用此答案中的一个选项:。