我正在尝试为一些遗留代码创建单元测试.我必须测试的一个类叫做FileDownloader,它只有以下一个方法:
public void Transmit(string fileName, HttpResponse response, DownloadFileType fileType, byte[] content)
{
response.Clear();
response.ClearHeaders();
response.ContentType = "application/xls";
response.AddHeader("content-disposition", "attachment; filename=" + HttpContext.Current.Server.UrlEncode(fileName));
response.BinaryWrite(content);
response.End();
response.Flush();
}
Run Code Online (Sandbox Code Playgroud)
我不允许重构这个代码(这本来是理想的!).
为了测试这个,我决定根据下面的文章创建一个假的HttpContext
有了这个,我可以在测试执行期间获得假的HttpContext,但是伪造HttpResponse存在问题.
以下是我的测试结果:
[SetUp]
public void SetUp()
{
mocks = new MockRepository();
FakeHttpContext.CreateFakeHttpContext();
}
[Test]
public void ShouldTransmitHttpResponseInTheSpecifiedFormat()
{
FileDownloader downloader = new FileDownloader();
string path = "..\\..\\Fakes\\DummyDownloadReportsTemplate.xls";
byte[] bytes = ReadByteArrayFromFile(path);
downloader.Transmit("test.xls", new HttpResponse(new StringWriter()), DownloadFileType.Excel, bytes);
}
Run Code Online (Sandbox Code Playgroud)
我正在将自定义创建的HTTPResponse对象传递给该方法.当它命中"response.BinaryWrite(content)"行时抛出以下异常:
System.Web.HttpException:使用自定义TextWriter时,OutputStream不可用.
我不确定我究竟应该在这里断言...因此在测试中没有断言.这是测试这种方法的正确方法......任何想法.请指教 ?
谢谢
基本上假设你有一些收藏:
public class FurCollection : IEnumerable<FurStrand>
{
public IEnumerator<FurStrand> GetEnumerator()
{
foreach(var strand in this.Strands)
{
yield return strand;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
Run Code Online (Sandbox Code Playgroud)
这可以接受吗?或者这是容易出错还是不好的做法?我几乎总是使用IEnumerator<T>但我仍然希望非通用版本稳定并正确实现.
目前我正在使用sqlite构建一个Windows应用程序.在数据库中有一个表说User,在我的代码中有一个Repository<User>和一个UserManager.我认为这是一个非常常见的设计.在存储库中有一个List方法:
//Repository<User> class
public List<User> List(where, orderby, topN parameters and etc)
{
//query and return
}
Run Code Online (Sandbox Code Playgroud)
这带来了一个问题,如果我想做一些复杂的事情UserManager.cs:
//UserManager.cs
public List<User> ListUsersWithBankAccounts()
{
var userRep = new UserRepository();
var bankRep = new BankAccountRepository();
var result = //do something complex, say "I want the users live in NY
//and have at least two bank accounts in the system
}
Run Code Online (Sandbox Code Playgroud)
你可以看到,返回List<User>会带来性能问题,因为查询的执行时间早于预期.现在我需要将其更改为IQueryable<T>:
//Repository<User> class
public TableQuery<User> List(where, orderby, topN parameters …Run Code Online (Sandbox Code Playgroud) 这种情况发生在C#和Java中,所以我认为这不是一个bug,只是想知道为什么.
var s = "";
var lower = s.ToLower();
var upper = s.ToUpper();
if (!lower.Equals(upper, StringComparison.OrdinalIgnoreCase))
{
//How can this happen?
}
Run Code Online (Sandbox Code Playgroud)
根据这个页面,""的小写是"",与IgnoreCase选项相比,它们应该相等.为什么他们不平等?
也许有点棘手,但我想知道为什么.在System.Linq.Enumerable.cs的System.Core.dll,我们有:
public static int Count<TSource>(this IEnumerable<TSource> source);
Run Code Online (Sandbox Code Playgroud)
在我的代码中,我正在做一些邪恶的事:
namespace Test
{
public static class Extensions
{
public static int Count<TSource>(this IEnumerable<TSource> source)
{
return -1; //evil code
}
}
//commented temporarily
//public static class CommentedExtensions
//{
// public static int Count<TSource>(this IEnumerable<TSource> source)
// {
// return -2; //another evil code
// }
//}
public static void Main(string[] args)
{
Console.WriteLine(Enumerable.Range(0,10).Count()); // -1, evil code works
Console.Read();
}
}
Run Code Online (Sandbox Code Playgroud)
如果我取消注释CommentedExtensions,我将收到一个编译错误,说"这个调用是不明确的blabla",如预期的那样.但为什么我第一次没有得到这个错误?这也很暧昧!
编辑经过另一次测试后,我发现如果扩展方法位于不同的命名空间中,我将不会遇到编译错误,即使它们完全相同.为什么允许这样做?它在c#中引入了模糊的方法调用.
EDIT2我知道其实两个 …
当我在visual studio 2012 RC中编译我的应用程序时,我可以看到bin\项目源文件夹中按预期生成的文件夹,其中有一个foo.exe,看起来像应用程序的条目.当我开始调试应用程序时,它的图标被放在开始屏幕上,我可以找到创建的新文件夹
C:\用户\人\应用程序数据\本地\包\ xxxxx_xxxxxx
但是我在这个文件夹中找不到foo.exe,即使我搜索了整个磁盘.似乎win8应用程序具有与旧Windows程序不同的安装/部署机制.我的问题是:
(1)部署/安装win8应用程序的方式/位置?
(2)我想\AppData\Local\Packages\xxxxx_xxxxxx\LocalState用作本地数据文件夹(ApplicationData.Current.LocalFolder在代码中等于),但是当右键单击开始屏幕图标并按"卸载"时,整个文件夹被删除,没有任何警告.有没有更好的地方存储本地数据?或者我需要SQLite?例如,我的应用程序写入所有崩溃消息error.txt,显然我不能在这种情况下使用sqlite,如果我放入error.txtLocalState文件夹,用户可能已经卸载了应用程序,然后我去找他看看是什么error.txt.另一种情况是:用户想要卸载应用程序,但保留其本地数据(文件).显然ApplicationData.Current.LocalFolder不是一个好选择.
假设我有10N个项目(我需要通过http协议来获取它们),在代码N中开始启动任务以获取数据,每个任务依次获取10个项目。我把这些东西放在一个盒子里ConcurrentQueue<Item>。之后,将以不安全线程的方法一一处理这些项目。
async Task<Item> GetItemAsync()
{
//fetch one item from the internet
}
async Task DoWork()
{
var tasks = new List<Task>();
var items = new ConcurrentQueue<Item>();
var handles = new List<ManualResetEvent>();
for i 1 -> N
{
var handle = new ManualResetEvent(false);
handles.Add(handle);
tasks.Add(Task.Factory.StartNew(async delegate
{
for j 1 -> 10
{
var item = await GetItemAsync();
items.Enqueue(item);
}
handle.Set();
});
}
//begin to process the items when any handle is set
WaitHandle.WaitAny(handles);
while(true)
{
if (all handles …Run Code Online (Sandbox Code Playgroud) 在我的Windows 8应用程序中有一个全局类,其中有一些静态属性,如:
public class EnvironmentEx
{
public static User CurrentUser { get; set; }
//and some other static properties
//notice this one
public static StorageFolder AppRootFolder
{
get
{
return KnownFolders.DocumentsLibrary
.CreateFolderAsync("theApp", CreationCollisionOption.OpenIfExists)
.GetResults();
}
}
}
Run Code Online (Sandbox Code Playgroud)
您可以看到我想在项目的其他位置使用应用程序根文件夹,因此我将其设置为静态属性.在getter中,我需要确保根文件夹存在,否则创建它.但这CreateFolderAsync是一个异步方法,这里我需要一个同步操作.我试过了,GetResults()但它抛出一个InvalidOperationException.什么是正确的实施?(package.appmanifest已正确配置,实际创建了该文件夹.)
当前在我的模型类中,我有一些JSON.NET属性,例如
public class MyModel
{
[JsonProperty("_anothername")]
[JsonConverter(typeof(MyCustomConverter))]
public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
是否有其他解决方案不会“污染”我的模型类?合同解析器可能有效,但是它太重了。我想要这样的东西:
var contract = new JsonContract<MyModel>();
contract.Property(m => m.Name)
.HasAlias("_anothername")
.HasConverter<MyCustomConverter>();
JsonConvert.SerializeObject(myModelInstance, contract);
Run Code Online (Sandbox Code Playgroud)
理想情况下,模型类对JSON.NET一无所知,并且该项目不应具有JSON.NET参考。
编辑:也许其他一些JSON库可以工作,但是我不想涉及另一个库,因为JSON.NET在该项目中被广泛使用。
更新:似乎合同解析器是执行此操作的标准方法,我发现此库接近我的期望。稍后,我将尝试编写自己的实现。
使用字符串插值使我的字符串格式看起来更加清晰,但是.ToString()如果我的数据是值类型,我必须添加调用。
class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
var person = new Person { Name = "Tom", Age = 10 };
var displayText = $"Name: {person.Name}, Age: {person.Age.ToString()}";
Run Code Online (Sandbox Code Playgroud)
这.ToString()使得格式更长更难看。我试图摆脱它,但它string.Format是一个内置的静态方法,我无法注入它。你对此有什么想法吗?而且既然字符串插值是 的语法糖string.Format,为什么.ToString()在生成语法糖背后的代码时不添加调用呢?我认为这是可行的。
c# ×10
.net ×7
async-await ×2
asynchronous ×2
architecture ×1
httpresponse ×1
ienumerable ×1
java ×1
json ×1
json.net ×1
linq ×1
mocking ×1
nunit ×1
string ×1
task ×1
testing ×1
unicode ×1
waithandle ×1
windows-8 ×1