けさらんぱさらん

方向性は定めず、ただ思いつくままに

とりあえずASP.NET5 beta7をUbuntuで動かしてみる

UbuntuでASP.NET5 beta7が動いたのでメモ

参考にしたサイト
Ubuntu Desktop で ASP.NET 5 Beta7 を CoreCLR で動かす - きよくらの備忘録
Installing ASP.NET 5 On Linux — ASP.NET 0.0.1 documentation

環境は、Azure上のUbuntu Server 15.04
素の状態から始めます。

まあ上記サイトの手順ほぼそのままですが、monoは入れてません。
説明なし
つらつらとコマンドだけ並べておく

sudo apt-get install unzip
curl -sSL https://raw.githubusercontent.com/aspnet/Home/dev/dnvminstall.sh | DNX_BRANCH=dev sh && source ~/.dnx/dnvm/dnvm.sh
dnvm upgrade -r coreclr
sudo apt-get install libunwind8 gettext libssl-dev libcurl3-dev zlib1g
sudo apt-get install make automake libtool curl
curl -sSL https://github.com/libuv/libuv/archive/v1.4.2.tar.gz | sudo tar zxfv - -C /usr/local/src
cd /usr/local/src/libuv-1.4.2
sudo sh autogen.sh
sudo ./configure
sudo make
sudo make install
sudo ldconfig

動くかどうかサンプルで試します

git clone https://github.com/aspnet/Home.git
cd Home/samples/1.0.0-beta7/HelloMvc
dnu restore

起動します

dnx kestrel

Azureだとポートが空いてないので空けておきます
monoインストールしないでもとりあえず動きました。
それ以上はまだ触ってないのでなんともかんとも

Moqでprotectedメソッドをモックする

通常は、テストしたいクラスが利用しているクラスのpublicメソッドをモックしますが
たまに自クラスのprotectedメソッドをモックしたい時があります。
(そりゃ設計が悪いって話もあるでしょうが、ここでは置いておきましょう)


こんなクラスがあります。

public class Hoge
{
    public bool Foo()
    {
        return Bar();
    }

    protected virtual bool Bar()
    {
       return true;
    }
}

Barメソッドをモックしてみます

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Moq.Protected;

namespace MoqSample
{
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestMethod1()
        {
            var mock = new Mock<Hoge>();
            mock.Protected().Setup<bool>("Bar").Returns(false);

            Assert.IsFalse(mock.Object.Foo());
        }
    }
}


Moq.Protectedをusingしてください。
あとは、まあ見たままですかね
Setupメソッドの型引数なしバージョンだとReturnsが無いので注意

Knockout.jsの初期値をDOMから取得する

Knockout.jsを使うときにたまに困るのがDOMの値を初期値にしたい時です。
なんか地道にJQueryでデータを取得してプロパティに代入してたのですが
ちょっと調べてみたらカスタマイズしてDOMからデータを取得することができました。
いろいろやり方はあるのでしょうが、私はこんな感じで実装してみました。

ko.bindingHandlers.valueWithInit = {
    init: function (element, valueAccessor, allBindingsAccessor, data, context) {
        var property = valueAccessor(), value = element.value;
        property(value);
        ko.bindingHandlers.value.init(element, valueAccessor, allBindingsAccessor, data, context);
    },
    update: ko.bindingHandlers.value.update
};

ko.bindingHandlers.textWithInit = {
    init: function (element, valueAccessor, allBindingsAccessor, data, context) {
        var property = valueAccessor(), text = $(element).text();
        property(text);
        ko.bindingHandlers.text.init(element, valueAccessor, allBindingsAccessor, data, context);
    },
    update: ko.bindingHandlers.text.update
};

ko.bindingHandlers.checkedWithInit = {
    init: function (element, valueAccessor, allBindingsAccessor, data, context) {
        var property = valueAccessor(), checked = element.checked;
        property(checked);
        ko.bindingHandlers.checked.init(element, valueAccessor, allBindingsAccessor, data, context);
    },
    update: ko.bindingHandlers.checked.update
};


これをvalueとかtextバインディングみたいに

<input name="FirstName" type="text" data-bind="valueWithInit: firstName">

こんな感じでかけます。
これですっきり

ChainingAssertionでテストをエレガントに

いつもの通りひさしぶりのブログです。
以前から使っている@neuecc先生作のChainingAssertionについて書きます。
基本的な使い方は、こんな感じ

var actual = Add(5,3);
actual.Is(8);

MSTestだと

Assert.AreEqual(8, actual);

う~ん


MSTestがイケてないところの1つに例外のテストがあります。

[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void 例外が発生する()
{
  // 例外が発生する処理
}

発生する例外を属性に設定してあげればOKです。
これはこれで良さそうな気もするのですが、
例外が発生した後に別なチェックもしたいとかができない!


これをChainingAssertionだと

[TestMethod]
public void 例外が発生する()
{
  AssertEx.Throws<ArgumentException>(() => Add(5, 3));
  // 引き続きテスト
}

これであればこの処理の後に引き続きテストが続けられます。


例外メッセージを確認したい場合は、戻り値がExceptionになっているので

AssertEx.Throws<ArgumentException>(() => Add(5, 3)).Message.Is("正の数を指定してください");

てな感じで可能になります。
こうゆう設計は見習いたいなー


ということ皆さんChainingAssertion使いましょう

AutoMapperでUpperCamelCaseとPascalCaseをMapする

今年、初ブログだったりします。(気力がね・・・)

さてタイトルの通りAutoMapperでUpperCamelCaseとPascalCaseをMapしたい。
C#でUpperCamelCaseを使うことはほぼ無いのですが
DBがOracleだったりしてORMもシンプルなものだったりすると
UpperCamelCaseで定義したクラスに一旦受けざる負えない時もあります。
それを簡単にPascalCaseで定義したクラスに移したいって時の話です。
(まああまり需要は無いですかねー)

以前に@xin9leさんが、このような記事を書かれています。
AutoMapperで特定の命名規則で変換する - xin9le.net
基本的にはこれでできたのですが、これにプラスして
PascalCaseからUpperCamelCaseへのMapもしたいのです。
これがかなり嵌りました。

とりあえずググる
Automapper: How to leverage a custom INamingConvention? - Stack Overflow
こんな感じで出てきますが、CreateProfileしてWithProfileするやり方だとどうもうまく行きませんでした。

で、ようやくできたのがこのやり方


とりあえず適当に受け渡しするクラスを作ります。

class Employee
{
    public int EmployeeId { get; set; }
    public string EmployeeName { get; set; }
}

class EmployeeDataModel
{
    public int EMPLOYEE_ID { get; set; }
    public string EMPLOYEE_NAME { get; set; }
}


INamingConventionを実装するクラスを作ります。

public class UpperSnakeCaseNamingConvention : INamingConvention
{
    public string SeparatorCharacter { get { return "_"; } }

    public Regex SplittingExpression { get { return new Regex(@"[\p{Lu}0-9]+(?=_?)"); } }
}


Profileクラスを継承するクラスをUpperCamelCaseからPascalCaseに変換するクラスと
逆にPascalCaseからUpperCamelCaseに変換するクラスを作ります。

class UpperSnakeToPascalProfile : Profile
{
    public override string ProfileName
    {
        get
        {
            return "UpperScakeToPascal";
        }
    }

    protected override void Configure()
    {
        // こちらはSourceに対して上で作ったINamingConventionを実装したクラスを設定
        this.SourceMemberNamingConvention = new UpperSnakeCaseNamingConvention();

        // 上の設定でMapしたいクラスは、ここでCreateMapすること
        this.CreateMap<EmployeeDataModel, Employee>();
    }
}

class PascalToUpperSnakeProfile : Profile
{
    public override string ProfileName
    {
        get
        {
            return "PascalToUpperSnake";
        }
    }

    protected override void Configure()
    {
        // こちらはDestinationに対して上で作ったINamingConventionを実装したクラスを設定
        this.DestinationMemberNamingConvention = new UpperSnakeCaseNamingConvention();

        this.CreateMap<Employee, EmployeeDataModel>();
    }
}


で、これを呼び出してうまく行くかテストします。

[TestClass]
public class UnitTest1
{
    public UnitTest1()
    {
        // Mappingの設定をする
        Mapper.Initialize(config =>
            {
                // AddProfileで上で作成したProfileクラスを設定
                config.AddProfile<UpperSnakeToPascalProfile>();
                config.AddProfile<PascalToUpperSnakeProfile>();
            });

        Mapper.AssertConfigurationIsValid();
    }

    [TestMethod]
    public void TestMethod1()
    {
        var dm = new EmployeeDataModel { EMPLOYEE_ID = 1, EMPLOYEE_NAME = "山田太郎" };
        var dto = Mapper.Map<Employee>(dm);

        Assert.AreEqual(dm.EMPLOYEE_ID, dto.EmployeeId);
        Assert.AreEqual(dm.EMPLOYEE_NAME, dto.EmployeeName);
    }

    [TestMethod]
    public void TestMethod2()
    {
        var dto = new Employee { EmployeeId = 2, EmployeeName = "佐藤一郎" };
        var dm = Mapper.Map<EmployeeDataModel>(dto);

        Assert.AreEqual(dto.EmployeeId, dm.EMPLOYEE_ID);
        Assert.AreEqual(dto.EmployeeName, dm.EMPLOYEE_NAME);
    }
}

という感じでちゃんとMapすることができました。

TFS2013にPullRequestがきました

ひさしぶりのブログになってしまいました。

TFS2013 Update4でPullRequest機能が実装されました。
もしかしたらアクセスレベルがPremium以上とかになるんじゃないかと思ったんですけど
大丈夫でした。

こんな感じでプル要求のタブができてます。
f:id:cer1974:20141113220917p:plain:w600

で、プル要求
f:id:cer1974:20141113220938p:plain:w600
あとはメンドイので割愛

これでレビューとかマージとか楽になりますねー