好吧,让自己成为一个单独的MailService类来使用Outlook类(它本身就是一个单独的afaik)似乎是一个好主意。
一开始它运行得很好,但是一旦我尝试从我的appservice层为这个类设置单元测试(MS单元测试),所有地狱都崩溃了,我得到Runtime Callable Wrapper错误..
我错误地将MailService类设置为单例还是将Outlook作为单例类包装出错?
这是我的Mailservice类,其中包含以下方法之一:
public class MailService : IDisposable
{
private static MailService _instance;
private Outlook.ApplicationClass _app;
private Outlook.NameSpace _olNS;
private MailService()
{
_app = new Outlook.ApplicationClass();
_olNS = _app.GetNamespace("MAPI");
}
public static MailService Instance
{
get
{
if (_instance == null)
_instance = new MailService();
return _instance;
}
}
public void Dispose()
{
_app.Quit();
Marshal.ReleaseComObject(_app);
GC.Collect();
GC.WaitForPendingFinalizers();
}
public Outlook.Folder getFolderByPath(string sFolderPath)
{
Outlook.Folder olFolder = null;
if (sFolderPath.StartsWith(@"\\"))
{
sFolderPath = sFolderPath.Remove(0, 2);
}
string[] sFolders = sFolderPath.Split('\\');
try
{
olFolder = _app.Session.Folders[sFolders[0]] as Outlook.Folder;
if (olFolder != null)
{
for (int i = 1; i <= sFolders.GetUpperBound(0); i++)
{
Outlook.Folders subFolders = olFolder.Folders;
olFolder = subFolders[sFolders[i]] as Outlook.Folder;
if (olFolder == null)
{
return null;
}
}
}
return olFolder;
}
catch (Exception e)
{
LogHelper.MyLogger.Error("Error retrieving " + sFolderPath, e);
return null;
}
}
}
我的MS单元测试 单独工作,但在测试列表 中全部运行时则不行。在后一种情况下,只有第一次测试通过......
[TestMethod]
public void TestMonitorForCleanUpDone()
{
Assert.IsNotNull(MailService.Instance.getFolderByPath(olFolderDone));
}
[TestMethod]
public void TestMonitorForCleanUpIn()
{
Assert.IsNotNull(MailService.Instance.getFolderByPath(olFolderIn));
}
答案 0 :(得分:1)
对于初学者来说,你对IDisposable的实现并不好。
public void Dispose()
{
_app.Quit();
Marshal.ReleaseComObject(_app);
GC.Collect();
GC.WaitForPendingFinalizers();
}
你有几件事情错了..
由于您实施Dispose(),因此您正在使MailService类成为单例,因此您的生命周期管理存在问题。
您应该阅读properly implementing the IDisposable interface in .NET和on MSDN Magazine here。还要考虑当MailClass对象超出范围时会发生什么。以及如何在单元测试的环境中管理它。
答案 1 :(得分:1)
像往常一样,事实证明其他人之前遇到过这个问题,并写了一篇关于它的博客文章: http://blogs.msdn.com/b/martijnh/archive/2009/12/31/unit-testing-com-object-that-has-been-separated-from-its-underlying-rcw-cannot-be-used.aspx
为了防止博客文章消失,解决方案就是在MTA模式下运行单元测试。
“解决此问题的方法是使用XML编辑器打开testrunconfig文件并添加 &lt; ExecutionThread apartmentState =”MTA“/&gt; 元素对它“
<?xml version="1.0" encoding="utf-8"?>
<TestRunConfiguration name="Local Test Run" id="f3322344-5454-4ac5-82b7-fa5ba9c1d8f2" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
<ExecutionThread apartmentState="MTA" />
<Description>This is a default test run configuration for a local test run.</Description>
<TestTypeSpecific />
</TestRunConfiguration>