修复过程相对简单。然而,我想为我的NUnit套件编写一个单元测试,以确保该进程将继续能够处理非常大的文件。但是,在我的开发工作站上实际耗尽内存会使我的机器变慢,并且很耗时间。在版本控制中存储一个巨大的测试文件也是不好的主意。如果我可以人为地限制进程、线程或应用程序域只使用固定量的RAM,比如128兆字节,我可以制作一个更小的单元测试,不会让我的工作站崩溃。
有什么建议吗?是否有一些未经管理的API可以P/Invoke?
你不能使用模拟框架来进行内存分配并将其作为一个测试抛出OutOfMemoryException
吗?
话虽如此,如果你真的已经用完了内存,那么你的应用程序就没有太多安全的操作了,但是如果你可以至少优雅地失败,你的用户会感激你。
例如: 我曾经在一份工作中遇到过这样一种情况,我们实时显示工厂的3D模型。当我们尝试加载纹理时,模型变得非常大,我们会遇到内存不足的错误。我们通过确保代码处理空指针来保持应用程序的运行和渲染,即使其他代码认为应该存在纹理信息。
使用Mocking进行单元测试是最好的。实际上,通过抛出OOM异常来进行单元测试是不符合定义的。当处理内存时,您正在处理负载测试。如果您阅读此电子邮件底部的链接,您将发现,在最好的情况下,真正的OOM异常很难重现和调试。人为制造的OOM异常并不是异常的真正原因,因此不比用于测试的模拟对象更有趣。
坚持使用Mock进行单元测试。如果仍然遇到OOM异常,请在服务器上增加更多内存,并更经常地使进程重启/重新启动。
以下是我上一次与OOM异常斗争时收集的一些有趣阅读材料。总结:OOM异常发生在系统无法分配您请求的数量时 - 这并不意味着您的内存已用尽。
在进程中很容易引起内存不足异常。
只需创建一个循环,该循环以足够小而不会在大对象堆上的块分配内存(但不要太多,否则会导致异常),然后您可以尝试打开一个较小的文件,这将导致无法分配足够连续的内存来打开该文件,当您打开文件时,将出现OOM异常,而无需巨大的文件。就像这样...
List<byte[]> items = new List<byte[]>();
for (int i = 0; i < 10000; i++)
{
byte[] c = new byte[160000];
items.Add(c);
}
byte[] next = new byte[1000000000];
我不太明白你在这里想说什么。假设你以某种方式创建了一个人工小的“测试环境”,无法分配更大的内存块,因此会对较小的文件抛出OutOfMemoryExceptions异常。你获得了什么?单元测试旨在测试您是否可以在实际系统上处理更大的文件,对吧?
重要的是,您可以处理任何需要的大小的文件,在它们将在其上运行的任何系统上,除了尝试在该系统上的该文件之外,没有真正的方法来对其进行单元测试。
(较小但不那么重要的事情可能是您是否优雅地处理OutOfMemoryException,但您无需真正耗尽内存即可测试它;只需使您的方法偶尔抛出异常并观察它是否执行正确操作即可。)