我正在寻找有关.NET mvc控制器的有效单元测试的建议.
在我工作的地方,许多这样的测试使用moq来模拟数据层并断言某些数据层方法被调用.这似乎对我没用,因为它基本上验证了实现没有改变而不是测试API.
我还阅读了一些文章,建议检查返回的视图模型的类型是否正确.我可以看到提供一些价值,但仅凭它似乎不值得编写许多行代码的努力(我们的应用程序的数据模型非常庞大和复杂).
任何人都可以建议一些更好的控制器单元测试方法或解释为什么上述方法是有效/有用的?
谢谢!
我知道无法捕获.NET中的StackOverflowExceptions,删除它们的进程,并且没有堆栈跟踪.这在MSDN上正式记录.但是,我想知道这种行为背后的技术(或其他)原因是什么.所有MSDN都说:
在.NET Framework的早期版本中,您的应用程序可以捕获StackOverflowException对象(例如,从无限递归中恢复).但是,目前不鼓励这种做法,因为需要大量额外的代码来可靠地捕获堆栈溢出异常并继续执行程序.
什么是"重要的附加代码"?这种行为还有其他记录的原因吗?即使我们无法捕获SOE,为什么我们至少不能获得堆栈跟踪?几个同事和我只是沉没几个小时来调试生产StackOverflowException,这可能需要几分钟的堆栈跟踪,所以我想知道我是否有充分的理由让我受苦.
.NET 4.6引入了AsyncLocal<T>用于沿异步控制流流动环境数据的类.我以前用过CallContext.LogicalGet/SetData这个目的,我想知道两者在语义上是否以及以何种方式不同(除了明显的API差异,如强类型和缺乏对字符串键的依赖).
我在WebApi应用程序中设置了以下示例代码:
[HttpGet]
public double GetValueAction()
{
return this.GetValue().Result;
}
public async Task<double> GetValue()
{
return await this.GetValue2().ConfigureAwait(false);
}
public async Task<double> GetValue2()
{
throw new InvalidOperationException("Couldn't get value!");
}
Run Code Online (Sandbox Code Playgroud)
可悲的是,当GetValueAction被击中时,返回的堆栈跟踪是:
" at MyProject.Controllers.ValuesController.<GetValue2>d__3.MoveNext() in c:\dev\MyProject\MyProject\Controllers\ValuesController.cs:line 61 --- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
at MyProject.Controllers.ValuesController.<GetValue>d__0.MoveNext() in c:\dev\MyProject\MyProject\Controllers\ValuesController.cs:line 56"
Run Code Online (Sandbox Code Playgroud)
因此,我在跟踪中得到(损坏)GetValue2和GetValue,但没有提到GetValueAction.难道我做错了什么?是否有另一种模式可以让我获得更完整的堆栈跟踪?
编辑:我的目标不是编写依赖于堆栈跟踪的代码,而是使异步方法中的失败更容易调试.
当EF尝试从App.config加载信息时,我最近开始在我的单元测试(NUnit)代码中遇到以下异常:
System.Runtime.Serialization.SerializationException : Type is not resolved for member [my type name], [my assembly name]
Run Code Online (Sandbox Code Playgroud)
NUnit GUI运行器和R#的VS集成运行器都会发生这种情况.这是一个快速的单元测试,可以重现这个问题:
[Test]
public void Test()
{
// adding
// ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
// here fixes things, probably because the configuration is cached
CallContext.LogicalSetData("FooSlot", new Foo()); // removing this line fixes things
ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); // fails with above exception
}
[Serializable] // removing this gives a different exception complaining that Foo is not Serializable
public class Foo // : MarshalByRefObject // this fixes things
{
}
Run Code Online (Sandbox Code Playgroud)
使用融合日志查看器,我发现失败是由于
FILE_NOT_FOUND …
我正在尝试在EntityFramework NuGet包(版本6.1.3)中调试StackOverflow.为了查看堆栈帧,我需要EntityFramework.DLL和EntityFramework.SqlServer.DLL的PDB文件.但是,我似乎无法让Visual Studio从MSFT符号源或从SymbolSource.org下载它(我可以获得其他系统PDB和NewtonSoft.json之类的东西).EF PDB可以在任何地方使用吗?
我使用并发字典作为线程安全的静态缓存,并注意到以下行为:
如果在不同的线程上同时调用GetOrAdd,可能会多次调用addValueFactory,但是对于每个调用,它的键/值对可能不会添加到字典中.
我希望能够保证工厂只被召唤一次.有没有办法使用ConcurrentDictionary API执行此操作而不依赖于我自己的单独同步(例如锁定valueFactory)?
我的用例是valueFactory在动态模块中生成类型,所以如果同一个键的两个valueFactories同时运行,我点击:
System.ArgumentException: Duplicate type name within an assembly.
由于C#的Task是一个类,你显然无法将其转换Task<TDerived>为a Task<TBase>.
但是,你可以这样做:
public async Task<TBase> Run() {
return await MethodThatReturnsDerivedTask();
}
Run Code Online (Sandbox Code Playgroud)
是否有一个静态任务方法我可以调用来获取一个Task<TDerived>基本上只指向底层任务并转换结果的实例?我喜欢这样的东西:
public Task<TBase> Run() {
return Task.FromDerived(MethodThatReturnsDerivedTask());
}
Run Code Online (Sandbox Code Playgroud)
这种方法存在吗?是否仅为此目的使用异步方法有任何开销?
我有一个LINQ to实体模型与Table Per Hierarchy继承.我有一个基类型的查询,我想做特定的类型相关的逻辑.例如:
IQueryable<BaseType> base = ...
// this works fine
var result = base.Select(b => b is DerivedType1 ? 1 : 2).ToList();
// this doesn't compile to SQL
var result2 = base.Select(b => b is DerivedType1 ? ((DerivedType1)b).DerivedProperty : null).ToList();
Run Code Online (Sandbox Code Playgroud)
有没有办法做这样的事情而不分别处理每个派生类型的IQueryables:
// I'd rather not do this:
var resultA = base.OfType<DerivedType1>().Select(d => d.DerivedProperty);
var resultB = base.OfType<DerivedType2>().Select(d => default(int?));
var result = resultA.Concat(resultB).ToList();
Run Code Online (Sandbox Code Playgroud) 我有一个剃刀布局,如:
@using (var context = SetUpSomeContext()) {
<div>
Some content here
@RenderBody();
</div>
}
Run Code Online (Sandbox Code Playgroud)
并且看起来像:
@{
Layout = "MyLayout.cshtml";
}
<div>@SomethingThatDependsOnContextBeingSetUp()</div>
Run Code Online (Sandbox Code Playgroud)
当视图呈现时,SomethingThatDependsOnContextBeingSetUp执行之前SetUpSomeContext和失败.这看起来很奇怪,因为我希望RenderBody在布局中调用之前不执行.当我将其切换为使用"PageContent"部分而不是RenderBody时,一切都按预期工作.谁能解释这种行为?
c# ×9
.net ×3
async-await ×3
.net-4.6 ×1
appdomain ×1
caching ×1
concurrency ×1
controller ×1
linq ×1
nunit ×1
pdb ×1
razor ×1
stack-trace ×1
task ×1
unit-testing ×1