MvcContribのTestControllerBuilderでRequest.Files.Countを使用していますか?
-
05-07-2019 - |
質問
ASP.NET MVCには、アップロードされたファイルを処理するコントローラーアクションがあります。ただし、MvcContribの TestControllerBuilder
を使用中に Request.Files.Count
を呼び出す方法はないようです。
Request.Files
を抽象化することでこの問題を回避できることを知っています。私の質問は:
- 実際には、
TestControllerBuilder
を使用するときにRequest.Files.Count
を呼び出す直接的な方法はないのですか?それとも私は何か間違っているのですか? - Rhino Mocksを使用して
TestControllerBuilder
を使用しながら、Request.Files.Count
への呼び出しをスタブする方法はありますか? -
Request.Files.Count
を処理するためのリクエストまたはパッチをMvcContribに送信する必要があると思いますか?
サンプルコード:
Request.Files
コレクションに少なくとも1つのファイルがあることを確認したいので、アクションに次の条件があります:
public class MyController : Controller {
public ActionResult Upload() {
if (Request.Files == null || Request.Files.Count == 0)
ViewData.ModelState.AddModelError("File", "Please upload a file");
// do stuff
return View();
}
}
MvcContribの TestControllerBuilder
を使用して、コントローラーテスト用のテストダブルを作成しています。ただし、 Request.Files.Count
の呼び出しは常に例外をスローするようです。たとえば、次のNUnitテストを実行すると、 Request.Files.Count
への呼び出しで controller.Upload()
への呼び出し中に NotImplementedException
がスローされます。
[Test]
public void Upload_should_return_default_view_given_one_file() {
MyController controller = new MyController();
TestControllerBuilder controllerBuilder = new TestControllerBuilder();
controllerBuilder.InitializeController(controller);
controllerBuilder.Files["file"] =
MockRepository.GenerateStub<HttpPostedFileBase>();
var result = controller.Upload() as ViewResult;
Assert.That(result.ViewData.ModelState.IsValid, Is.True);
result.AssertViewRendered().ForView(string.Empty);
}
また、 Request.Files.Count
への呼び出しをスタブ化して無駄にしました(Rhino Mocksを使用しています)。以下のいずれも機能しません( controller
や controllerBuilder
をスタブに変更しても):
controllerBuilder.Stub(cb => cb.HttpContext.Request.Files.Count).Return(1);
controller.Stub(c => c.Request.Files.Count).Return(1);
ありがとう
解決
I パッチをGithubでMvcContrib mantainersに送信したが、変更は非常に大きい簡単に作成できますが、問題はHttpFileCollectionBaseがCount()およびthis [int index]メソッドを実装していないため、MvcContribのWriteableHttpFileCollectionでオーバーライドする必要があることです。
完全を期すため、ここにコードを貼り付けます。WriteableHttpFileCollectionクラスに追加する必要があります。
public override HttpPostedFileBase this[int index]
{
get { return files[AllKeys[index]]; }
}
public override int Count
{
get { return files.Count; }
}
他のヒント
このアプローチを使用して問題を解決しました。
テストのセットアップ: string fileName =&quot; Test 1.pdf&quot ;; FileStream stream = File.OpenRead(&quot; log4net.config&quot;); MockRepository mock = new MockRepository();
builder.Files[fileName] = mock.CreateMock<HttpPostedFileBase>();
using (mock.Record())
{
Expect.Call(builder.Files[fileName].FileName)
.Return(fileName);
Expect.Call(builder.Files[fileName].ContentType)
.Return(contentType);
Expect.Call(builder.Files[fileName].ContentLength)
.Return(Convert.ToInt32(stream.Length.ToString()));
Expect.Call(builder.Files[fileName].InputStream)
.Return(stream);
}
モックの使用:
foreach(string key in Request.Files.AllKeys)
{
int lenght = Request.Files[key].ContentLength;
if (lenght > 0)
{
Document document = new Document();
string fileName = Request.Files[key].FileName;
byte[] content= new byte[Convert.ToInt32(lenght)];
Request.Files[key].InputStream.Read(content, 0, content.Length);
document.SetContent(content);
document.MimeType = Request.Files[key].ContentType;
// do whatever you want...
}
}