1

(編集** 合格した単体テストをコンパイルして実行するためのコードを取得できました。コードの修正に加えて、単体テストを無期限に実行する VS2010 に問題がありました。変更された dll ファイルを置き換える必要がありました。 vs 2012 のインストールが中止されたとき. ページの下部にコントローラーと単体テストの変更を投稿しました. 回答を投稿したすべての人に感謝します.)

これは、コーディングについてオンラインで尋ねた最初の質問です。私は約 1 年間、無料のチュートリアルを使用して C# .NET およびその他の関連事項を学んでいます。これまでのところ、すべてを自分で調査してトラブルシューティングすることができました。私は今、未知の領域に足を踏み入れ始めていますが、答えが見つからないようです。

「7日間でMVCモデルビューコントローラーを段階的に学ぶ」というチュートリアルに取り組んでいます。リンクは次のとおりです 。 http://www.codeproject.com/Articles/259560/Learn-MVC-Model-view-controller-Step-by-Step-in-7

エラーの推奨リンクを調査しました。

Error 'Mvccustomer.Models.Customer' does not contain a definition for 'DisplayCustomer'        and no extension method 'DisplayCustomer' accepting a first argument of type     'Mvccustomer.Models.Customer' could be found (are you missing a using directive or an     assembly reference?)

私が直面している問題は、誰かが同様のファイル参照を使用して単体テストを作成しているような状況を見つけることができないように見えることです。私はMVCと単体テストにまったく慣れていません。

チュートリアルの問題の 1 つは、作成者がビデオで 1 つの名前空間/ファイル名のセットを使用し、別のセットをチュートリアルで使用していることです。私は自分でその問題をトラブルシューティングすることができました。たとえば、最初はプロジェクト名として「Mvccustomer」を使用していましたが、初日の 4 番目または 5 番目のラボでは、「Mvcinputscreen」と呼んでいます。プロジェクトでの顧客クラスの参照方法に問題があるのではないかと思いますが、今のところわかりません。

エラーが発生する単体テストは次のとおりです。

using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Mvccustomer.Models;

namespace MvcUnitTest
{
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void DisplayCustomer()
        {
            Customer obj = new Customer();
            var varresult = obj.DisplayCustomer();
            Assert.AreEqual("DisplayCustomer", varresult.ViewName);
        }
    }
}

顧客クラスは次のとおりです。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Mvccustomer.Models;

namespace Mvccustomer.Models
{
    public class Customer
    {
        public int Id { set; get; }
        public string CustomerCode { set; get; }
        public double Amount { set; get; }
    }
}

これはディスプレイ カスタマー ビューです。

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<Mvccustomer.Models.Customer>"     %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>DisplayCustomer</title>
</head>
<body>
    <div>
    The customer id is <%= Model.Id %> <br />

    The customer id is <%= Model.CustomerCode %> <br />

    <%if (Model.Amount > 100)
      {%>
    This is a priveleged customer.
    <% }
      else
      { %>
    This is a normal customer
    <%} %>

    </div>
</body>
</html>

そして、顧客コントローラー:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Mvccustomer.Models;


namespace Mvccustomer.Controllers
{
    public class CustomerController : Controller
{
    //
    // GET: /Customer/

    public ActionResult Index()
    {
        return View();
    }

    public ActionResult FillCustomer()
    {
        return View();
    }
    public ActionResult DisplayCustomer(Customer obj)
    {
        return View(obj);
    }

}

}

プロジェクトの要素をさらに投稿する必要がある場合はお知らせください。Mvccustomer プロジェクトをビルドすると、エラーなしで正常にコンパイルされます。問題を引き起こしているのは単体テストだけです。この質問は少し入り組んでいると思いますが、建設的な批判とともに得られる学習経験を楽しみにしています。ありがとうございました。

最終的に機能した編集されたコントローラーと単体テスト:

カスタマーコントローラー:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Mvccustomer.Models;
using Mvccustomer.Controllers;

namespace Mvccustomer.Controllers
{
public class CustomerController : Controller
{
    //
    // GET: /Customer/

    public ActionResult Index()
    {
        return View();
    }

    public ActionResult FillCustomer()
    {
        return View();
    }

    [HttpPost]
    public ActionResult DisplayCustomerView(CustomerModel customerModel)
    {
      var myView = View("DisplayCustomerView", customerModel);
      //myView.ViewName = "DisplayCustomer";
      return myView;
    }

}
}

編集された単体テスト:

using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Mvccustomer.Models;
using Mvccustomer.Controllers;
using System.Web.Mvc;

namespace MvcUnitTest
{


[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void DisplayCustomer()
    {
      // instantiates new instance of CustomerController class
      CustomerController controller = new CustomerController();

      var customer = new CustomerModel();

      var customerViewActionResult = controller.DisplayCustomerView(customer);
      var customerViewViewResult = customerViewActionResult as ViewResult;


      Assert.AreEqual("DisplayCustomerView", customerViewViewResult.ViewName);

    }
}
}
4

4 に答える 4

2
CustomerController obj = new CustomerController();
var result = obj.DisplayCustomer(new Customer()) **as ViewResult**;
Assert.AreEqual("Expected", result.ViewName);
于 2012-11-14T13:11:13.430 に答える
1

コントローラーによって返されるはずのビュー名をテストしていますが、コントローラーを作成していません。代わりに、ではなくを呼び出し.DisplayCustomer()ています。CustomerCustomerController

また、コードをもう少し説明します。単体テスト関数の名前は、テスト対象を説明する必要があります。変数名は、それらが何であるかを説明する必要があります (obj意味がないため、悪い名前です)。

他のプログラマーのコードを読んでその仕組みを理解する必要があるか、2 年後に自分のコードに戻ってその仕組みを思い出そうとすることを検討してください。物事に説明的な名前を付けると役立ちます。私はあなたのテストを次のように書き直します:

    [TestMethod]
    public void DisplayCustomer_ReturnsViewNamed_DisplayCustomer()
    {
        const string expectedViewName = "DisplayCustomer";
        var customer = new Customer();
        var controllerUnderTest = new CustomerController();

        var result = controllerUnderTest.DisplayCustomer(customer);

        Assert.AreEqual(expectedViewName, result.ViewName);
    }

プログラミングの本を読むのが好きなら、Robert Martin のClean Codeを強くお勧めします。Java のコード例で書かれていますが、Java は構文的に C# に近く、コードを読みやすく、シンプルに、よく整理するための優れた本です。コーディング時によく参照する本からのメモのチートシートを保管しています。


編集:

あなたの新しいエラーについて:

'System.Web.Mvc.ActionResult' には 'ViewName' の定義が含まれておらず、タイプ 'System.Web.Mvc.ActionResult' の最初の引数を受け入れる拡張メソッド 'ViewName' が見つかりませんでした (using ディレクティブがありませんか?またはアセンブリ参照?)

コントローラーのメソッド シグネチャは次のとおりです。

public ActionResult DisplayCustomer(Customer obj)

オブジェクトを返しActionResultます。プロパティ.ViewNameはこのタイプに存在しません。実際には のプロパティですViewResult

DisplayCustomer()コントローラーのメソッド内の行は次を返します。

return View(obj);

このView()メソッドは実際には を返しますViewResultが、ViewResultクラスは を拡張しますActionResult:

public class ViewResult : ActionResult

したがって、メソッド シグネチャが に設定されていても問題ありActionResultませんが、実際には が であるため常に返しViewResultます。(典型的な OO 継承のものですが、うまくいけば、この部分は今のところ理にかなっています)。ViewResult ActionResult

あなたのテストではDisplayCustomer()、テストが知っている限り呼び出すと、メソッドシグネチャだけが必要です。これは、コンパイラにActionResult. したがって、コンパイラは存在しないクラスのプロパティ名ViewNameを見つけようとしています。Actionresult

これを修正するには、次の 2 つの方法があります。

1 つは、テストで結果を単純にキャストすることです。

var varresult = (ViewResult)obj.DisplayCustomer();

または、そのメソッドは常に を返すためViewResult、メソッド シグネチャを変更して、このより具体的な型を返すことを示すことができます。

public ViewResult DisplayCustomer(Customer obj)
{
    return View(obj);
}
于 2012-11-14T13:07:58.327 に答える
1

簡単にするために、モッキングフレームワークを使用しないようにこれを要約しようとしましたtry/catch

問題が発生している理由の 1 つに気付きました。メソッドはnotDisplayCustomer()を返すはずです。ViewResultActionResult

ただし、ビュー名の取得は が呼び出されるまで行われないため、チュートリアルはまだ機能しません。ExecuteResult()

   [TestMethod]
    public void DisplayCustomerTest_FindsCorrectViewName()
    {
        var expected = "DisplayCustomer";

        var obj = new CustomerController();
        var cContext = new ControllerContext();

        cContext.RouteData.Values.Add("action", expected);
        cContext.RouteData.Values.Add("controller", "Customer");

        var actionResult = obj.DisplayCustomer(new Customer());

        //not necessary but helpful
        Assert.IsInstanceOfType(actionResult, typeof(ViewResult));

        //down cast
        var vResult = actionResult as ViewResult;

        try // the view name is populated early, and we don't care about what else it does
        {
            vResult.ExecuteResult(cContext);
        }
        catch (NotImplementedException) {} //catch the most specific error type you can

        Assert.AreEqual(expected, vResult.ViewName);

    }

これを行うためのより興味深い方法、またはより高度な方法については(意見の問題であり、適切なモックフレームワークを利用した回答が欠けているようです)

単体テスト用に ViewResult.ViewName が空の文字列であるビュー名を取得します

ダウンキャストの説明

スタイリングを許してください。自宅にResharperまたはStyleCopがインストールされていません。

単体テストの命名規則については、単体テストの命名のベスト プラクティスを検討してください

于 2012-12-17T18:20:47.940 に答える