Test

我!阿斯匹.多莱特!加油!新的方向!

行路难,行路难,多歧路,今安在。

长风破浪会有时,直挂云帆济沧海。
2011年,人生需要改变!RhinoMock(2)---Stubs & Mocks

•stub:简单,只关心输入,输出。
•Mock:复杂,包含交互逻辑
•Interaction-based testers对于所有次要对象编写mocks。State-based testers仅仅对于那些不实际使用real object的object编写stubs
--------------------英文定义

Stubs provide canned answers to calls made during the test, usually not responding at all to anything outside what’s programmed in for the test. Stubs may also record information about calls, such as an email gateway stub that remembers the messages it ’sent’, or maybe only how many messages it ’sent’.



Rhino mock 实现了方法管道模式,这样可以更自然的调用方法,并且保持调用的顺序。

Expect.Call

This method is not safe for multi threading scenarios! If you need to record in a multi threading environment, use the On method, which can handle multi threading scenarios.



------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

We can then use state verification on the stub like this.

class OrderStateTester...
public void testOrderSendsMailIfUnfilled() {
Order order = new Order(TALISKER, 51);
MailServiceStub mailer = new MailServiceStub();
order.setMailer(mailer);
order.fill(warehouse);
assertEquals(1, mailer.numberSent());
}Of course this is a very simple test - only that a message has been sent. We've not tested it was send to the right person, or with the right contents, but it will do to illustrate the point.

Using mocks this test would look quite different.

class OrderInteractionTester...
public void testOrderSendsMailIfUnfilled() {
Order order = new Order(TALISKER, 51);
Mock warehouse = mock(Warehouse.class);
Mock mailer = mock(MailService.class);
order.setMailer((MailService) mailer.proxy());

mailer.expects(once()).method("send");
warehouse.expects(once()).method("hasInventory")
.withAnyArguments()
.will(returnValue(false));

order.fill((Warehouse) warehouse.proxy());
}
}In both cases I'm using a test double instead of the real mail service.

There is a difference in that the stub uses state verification while the mock uses behavior verification.

The difference is in how exactly the double runs and verifies

因为其在测试中所担任的角色,大部分stub的实现就是对于带特定参数的方法调用返回已定义好的数据。在mock社区看来,最本质的区别就在于mock所具有的expectation setting机制,利用此机制可以测试mock上哪些方法被调用了。 Mockists通常把一个刚刚返回值的mock object叫做'just a stub'。所以,一种观察mocks和stubs的区别的方法就是在使用mock的时候人们是把建立并且测试expectations当作测试的一部分的。似乎太简单了点 - 我也曾经编写过做一些简单形式expectation检查的stub(这些检查可能是设置一个布尔值来代表某个method是否被调用)。但是我想我们有理由认为expectations对于stubs来说是一种稀有的特性,而对于mocks来说是主要的特性。




总结

1。 Stub 比Mock来的简单,粗糙。

2。 Stub 注意关注主体对象,简单的输入,输出,不关注内部处理,交互。

3。 Mock 包含Expectation,关注方法是否被调用,顺序如何。





二。实例(http://github.com/JonKruger/RhinoMocksExamples/raw/master/src/RhinoMocksExamples/RhinoMocksExamples/RhinoMocksTests.cs)



// Here are some tests that will show what how to do everything
// you would want to do with Rhino Mocks. You can also read the
// documentation (which is pretty good) here:
// http://ayende.com/Wiki/Rhino+Mocks+3.5.ashx

// The Rhino Mocks syntax has changed drastically over the years,
// definitely for the good. You may find old blog posts out there
// showing how to do it the old way. Just ignore them and be
// glad that you didn't have to do it the old way.

// Let's create some sample classes that we'll work with.

public interface ISampleClass
{
string Property { get; set; }
void VoidMethod();
int MethodThatReturnsInteger(string s);
object MethodThatReturnsObject(int i);
void MethodWithOutParameter(out int i);
void MethodWithRefParameter(ref string i);

event EventHandler SomeEvent;
}

public class SampleClass
{
private string _nonVirtualProperty;
public string NonVirtualProperty
{
get { return _nonVirtualProperty; }
set
{
_nonVirtualProperty = value;
NonVirtualPropertyWasSet = true;
}
}

private string _virtualProperty;
public virtual string VirtualProperty
{
get { return _virtualProperty; }
set
{
_virtualProperty = value;
VirtualPropertyWasSet = true;
}
}

public string SetByConstructor { get; private set; }
public bool NonVirtualPropertyWasSet { get; set; }
public bool VirtualPropertyWasSet { get; set; }
public bool VoidMethodWasCalled { get; set; }
public bool VirtualMethodWasCalled { get; set; }
public bool NonVirtualMethodWasCalled { get; set; }

public event EventHandler SomeEvent;
public virtual event EventHandler SomeVirtualEvent;

public SampleClass()
{

}

public SampleClass(string value)
{
SetByConstructor = value;
}

public void VoidMethod()
{
VoidMethodWasCalled = true;
}

public virtual int VirtualMethod(string s)
{
VirtualMethodWasCalled = true;
return s.Length;
}

public IList<int> NonVirtualMethod(int i)
{
NonVirtualMethodWasCalled = true;
return new List<int> { i };
}

public void FireSomeVirtualEvent()
{
if (SomeVirtualEvent != null)
SomeVirtualEvent(this, EventArgs.Empty);
}
}

// Time for tests.

public class When_working_with_a_stub_of_an_interface : SpecBase
{
// "stub" == "fake"

[Test]
public void You_can_create_a_stub_by_calling_MockRepository_GenerateStub()
{
// This is the out-of-the-box way to create a stub in Rhino Mocks.
// Rhino Mocks will dynamically create a class that implements
// ISampleClass and return it to you.
var stub = MockRepository.GenerateStub<ISampleClass>();
}

[Test]
public void NBehave_gives_us_a_shorthand_way_of_creating_stubs()
{
// Less typing.
var stub = CreateStub<ISampleClass>();
}

[Test]
public void Calling_void_methods_will_do_nothing()
{
var stub = CreateStub<ISampleClass>();
stub.VoidMethod();
}

[Test]
public void Calling_methods_that_return_value_types_will_return_the_default_value_for_that_type()
{
var stub = CreateStub<ISampleClass>();
stub.MethodThatReturnsInteger("foo").ShouldEqual(0);
}

[Test]
public void Calling_methods_that_return_reference_types_will_return_null()
{
var stub = CreateStub<ISampleClass>();
stub.MethodThatReturnsObject(1).ShouldBeNull();
}

[Test]
public void You_can_tell_the_stub_what_value_to_return_when_is_method_is_called_with_specific_arguments()
{
var stub = CreateStub<ISampleClass>();

stub.Stub(s => s.MethodThatReturnsInteger("foo")).Return(5);

// calling the method with "foo" as the parameter will return 5
stub.MethodThatReturnsInteger("foo").ShouldEqual(5);

// calling the method with anything other than "foo" as the
// parameter will return the default value
stub.MethodThatReturnsInteger("bar").ShouldEqual(0);
}

[Test]
public void You_can_tell_the_stub_what_value_to_return_when_is_method_is_called_with_any_argument()
{
var stub = CreateStub<ISampleClass>();

stub.Stub(s => s.MethodThatReturnsInteger(Arg<string>.Is.Anything)).Return(5);

// now it doesn't matter what the parameter is, we'll always get 5
stub.MethodThatReturnsInteger("foo").ShouldEqual(5);
stub.MethodThatReturnsInteger("bar").ShouldEqual(5);
stub.MethodThatReturnsInteger(null).ShouldEqual(5);
}

[Test]
public void You_can_get_fancy_with_parameters_in_stubs()
{
var stub = CreateStub<ISampleClass>();

// Arg<>.Matches() allows us to specify a lambda expression that specifies
// whether the return value should be used in this case. Here we're saying
// that we'll return 5 if the string passed in is longer than 2 characters.
stub.Stub(s => s.MethodThatReturnsInteger(Arg<string>.Matches(arg => arg != null && arg.Length > 2)))
.Return(5);

stub.MethodThatReturnsInteger("fooo").ShouldEqual(5);
stub.MethodThatReturnsInteger("foo").ShouldEqual(5);
stub.MethodThatReturnsInteger("fo").ShouldEqual(0);
stub.MethodThatReturnsInteger("f").ShouldEqual(0);
stub.MethodThatReturnsInteger(null).ShouldEqual(0);
}

[Test]
public void Handling_out_parameters_in_stubs()
{
var stub = CreateStub<ISampleClass>();

// Here's how you stub an "out" parameter. The "Dummy" part is
// just to satisfy the compiler.
stub.Stub(s => s.MethodWithOutParameter(out Arg<int>.Out(10).Dummy));

int i = 12345;
stub.MethodWithOutParameter(out i);
i.ShouldEqual(10);
}

[Test]
public void Handling_ref_parameters_in_stubs()
{
var stub = CreateStub<ISampleClass>();

// Here's how you stub an "ref" parameter. The "Dummy" part is
// just to satisfy the compiler. (Note: Is.Equal() is part of
// the Rhino.Mocks.Contraints namespace, there is also an
// Is.EqualTo() in NUnit... you want the Rhino Mocks one.)
stub.Stub(s => s.MethodWithRefParameter(ref Arg<string>.Ref(Is.Equal("input"), "output").Dummy));

// If you call the method with the specified input argument, it will
// change the parameter to the value you specified.
string param = "input";
stub.MethodWithRefParameter(ref param);
param.ShouldEqual("output");

// If I call the method with any other input argument, it won't
// change the value.
param = "some other value";
stub.MethodWithRefParameter(ref param);
param.ShouldEqual("some other value");
}

[Test]
public void You_can_tell_the_stub_to_throw_an_exception_when_a_method_is_called()
{
var stub = CreateStub<ISampleClass>();

// calling the method with "foo" as the parameter will throw exception
stub.Stub(s => s.MethodThatReturnsInteger("foo")).Throw(new InvalidOperationException());

typeof(InvalidOperationException).ShouldBeThrownBy(
() => stub.MethodThatReturnsInteger("foo"));
}

[Test]
public void You_can_check_to_see_if_a_method_was_called()
{
var stub = CreateStub<ISampleClass>();

stub.MethodThatReturnsInteger("foo");

stub.AssertWasCalled(s => s.MethodThatReturnsInteger("foo"));
stub.AssertWasCalled(s => s.MethodThatReturnsInteger(Arg<string>.Is.Anything));
}

[Test]
public void You_can_check_to_see_if_a_method_was_called_a_certain_number_of_times()
{
var stub = CreateStub<ISampleClass>();

stub.MethodThatReturnsInteger("foo");
stub.MethodThatReturnsInteger("bar");

// this will pass
stub.AssertWasCalled(s => s.MethodThatReturnsInteger("foo"), o => o.Repeat.Once());

// call the method a second time
stub.MethodThatReturnsInteger("foo");

// now this will fail because we called it a second time
typeof (ExpectationViolationException).ShouldBeThrownBy(
() => stub.AssertWasCalled(s => s.MethodThatReturnsInteger("foo"), o => o.Repeat.Once()));

// some other options
stub.AssertWasCalled(s => s.MethodThatReturnsInteger("foo"), o => o.Repeat.Times(2));
stub.AssertWasCalled(s => s.MethodThatReturnsInteger("foo"), o => o.Repeat.AtLeastOnce());
stub.AssertWasCalled(s => s.MethodThatReturnsInteger("foo"), o => o.Repeat.Twice());
}

[Test]
public void You_can_check_to_see_if_a_method_was_not_called()
{
var stub = CreateStub<ISampleClass>();

stub.MethodThatReturnsInteger("foo");

stub.AssertWasNotCalled(s => s.MethodThatReturnsInteger("asdfdsf"));
stub.AssertWasNotCalled(s => s.MethodThatReturnsObject(Arg<int>.Is.Anything));
stub.AssertWasNotCalled(s => s.VoidMethod());
}

[Test]
public void You_can_get_the_arguments_of_calls_to_a_method()
{
var stub = CreateStub<ISampleClass>();

stub.MethodThatReturnsInteger("foo");
stub.MethodThatReturnsInteger("bar");

// GetArgumentsForCallsMadeOn() returns a list of arrays that contain
// the parameter values for each call to the method.
IList<object[]> argsPerCall = stub.GetArgumentsForCallsMadeOn(s => s.MethodThatReturnsInteger(null));
argsPerCall[0][0].ShouldEqual("foo");
argsPerCall[1][0].ShouldEqual("bar");
}

[Test]
public void If_you_set_a_property_the_getter_will_return_the_value()
{
var stub = CreateStub<ISampleClass>();

stub.Property = "foo";
stub.Property.ShouldEqual("foo");
}

[Test]
public void You_cannot_use_AssertWasCalled_with_properties_on_a_stub()
{
// But why would you need to? You can just get the value
// directly from the property.
var stub = CreateStub<ISampleClass>();

stub.Property = "foo";

// Don't do this
//stub.AssertWasCalled(s => s.Property);

// Just do this
stub.Property.ShouldEqual("foo");
}

[Test]
public void You_can_tell_events_on_a_stub_to_fire()
{
var stub = CreateStub<ISampleClass>();
var eventWasHandled = false;

// attach an event handler
stub.SomeEvent += (args, e) => eventWasHandled = true;

// raise the event
stub.Raise(s => s.SomeEvent += null, this, EventArgs.Empty);

eventWasHandled.ShouldBeTrue();
}

[Test]
public void You_can_do_arbitrary_stuff_when_a_method_is_called()
{
var stub = CreateStub<ISampleClass>();
stub.Stub(s => s.MethodThatReturnsInteger(Arg<string>.Is.Anything))
.Return(0) // you have to call Return() even though we're about to override it
.WhenCalled(method =>
{
string param = (string) method.Arguments[0];
method.ReturnValue = int.Parse(param);
});

stub.MethodThatReturnsInteger("3").ShouldEqual(3);
stub.MethodThatReturnsInteger("6").ShouldEqual(6);
}
}

public class When_working_with_a_mock_of_an_interface : SpecBase
{
// You can do pretty much everything with stubs. I don't see a reason
// to ever use mocks. If you want to know the technical academic difference
// between a mock and a stub, you can read about it here:
// http://martinfowler.com/articles/mocksArentStubs.html
//
// Personally I think it's all semantics and that it doesn't really matter.
// I'd recommend just using stubs with Rhino Mocks. But if you really care,
// here are the things that are different with mocks.

[Test]
public void You_can_create_a_stub_by_calling_MockRepository_GenerateMock()
{
var mock = MockRepository.GenerateMock<ISampleClass>();
}

[Test]
public void NBehave_gives_us_a_shorthand_way_of_creating_mocks()
{
// Less typing.
var mock = CreateDependency<ISampleClass>();
}

[Test]
public void You_can_check_to_see_if_a_property_was_set()
{
var mock = CreateDependency<ISampleClass>();

mock.Property = "foo";

mock.AssertWasCalled(s => s.Property = "foo");
}

[Test]
public void You_can_check_to_see_if_a_property_getter_was_called()
{
var mock = CreateDependency<ISampleClass>();

var value = mock.Property;

mock.AssertWasCalled(s => { var ignored = s.Property; });
}

[Test]
public void Another_way_to_verify_expectations_instead_of_AssertWasCalled()
{
var stub = CreateDependency<ISampleClass>();

// Here I'm setting up an expectation that a method will be called
stub.Expect(s => s.MethodThatReturnsInteger("foo")).Return(5);

var output = stub.MethodThatReturnsInteger("foo");
output.ShouldEqual(5);

// ... and now I'm verifying that the method was called
stub.VerifyAllExpectations();
}
}

public class When_working_with_a_partial_mock_of_a_concrete_class : SpecBase
{
[Test]
public void Here_is_how_you_create_a_partial_mock()
{
var mockRepository = new MockRepository();
var sampleClass = mockRepository.PartialMock<SampleClass>();
sampleClass.Replay();

// There is currently no special NBehave way to create a partial mock.
}

[Test]
public void You_can_pass_in_constuctor_arguments_and_Rhino_Mocks_will_pick_the_constructor_that_fits()
{
var mockRepository = new MockRepository();
var sampleClass = mockRepository.PartialMock<SampleClass>("foo");
sampleClass.Replay();

sampleClass.SetByConstructor.ShouldEqual("foo");
}

[Test]
public void Calling_non_virtual_methods_will_call_the_actual_method()
{
var mockRepository = new MockRepository();
var sampleClass = mockRepository.PartialMock<SampleClass>();
sampleClass.Replay();

sampleClass.VoidMethod();
sampleClass.VoidMethodWasCalled.ShouldBeTrue();
}

[Test]
public void Calling_virtual_methods_will_call_the_actual_method()
{
var mockRepository = new MockRepository();
var sampleClass = mockRepository.PartialMock<SampleClass>();
sampleClass.Replay();

sampleClass.VirtualMethod("foo").ShouldEqual(3);
sampleClass.VirtualMethodWasCalled.ShouldBeTrue();
sampleClass.AssertWasCalled(c => c.VirtualMethod("foo"));
}

[Test]
public void You_can_stub_a_virtual_method_and_give_it_a_return_value()
{
var mockRepository = new MockRepository();
var sampleClass = mockRepository.PartialMock<SampleClass>();
sampleClass.Replay();

sampleClass.Stub(c => c.VirtualMethod("foo")).Return(100);

sampleClass.VirtualMethod("foo").ShouldEqual(100);

// It's not actually going to run the real method since we stubbed it out.
sampleClass.VirtualMethodWasCalled.ShouldBeFalse();

sampleClass.AssertWasCalled(c => c.VirtualMethod("foo"));
}

[Test]
public void You_can_have_virtual_methods_throw_an_exception_when_they_are_called()
{
var mockRepository = new MockRepository();
var sampleClass = mockRepository.PartialMock<SampleClass>();

sampleClass.Stub(c => c.VirtualMethod("foo")).Throw(new InvalidOperationException());

sampleClass.Replay();

typeof(InvalidOperationException).ShouldBeThrownBy(
() => sampleClass.VirtualMethod("foo"));
}

[Test]
public void You_cannot_stub_a_non_virtual_method()
{
var mockRepository = new MockRepository();
var sampleClass = mockRepository.PartialMock<SampleClass>();

typeof(Exception).ShouldBeThrownBy(
() => sampleClass.Stub(s => s.NonVirtualMethod(1)).Return(new List<int> { 3 }));
}

[Test]
public void You_can_use_WhenCalled_with_virtual_methods()
{
var mockRepository = new MockRepository();
var sampleClass = mockRepository.PartialMock<SampleClass>();
sampleClass.Replay();

sampleClass.Stub(s => s.VirtualMethod(Arg<string>.Is.Anything))
.Return(0) // you have to call Return() even though we're about to override it
.WhenCalled(method =>
{
string param = (string) method.Arguments[0];
method.ReturnValue = int.Parse(param);
});

sampleClass.VirtualMethod("3").ShouldEqual(3);
sampleClass.VirtualMethod("6").ShouldEqual(6);
}

[Test]
public void You_cannot_use_WhenCalled_with_non_virtual_methods()
{
var mockRepository = new MockRepository();
var sampleClass = mockRepository.PartialMock<SampleClass>();
sampleClass.Replay();

typeof (Exception).ShouldBeThrownBy(
() =>
sampleClass.Stub(s => s.NonVirtualMethod(Arg<int>.Is.Anything))
.Return(null) // you have to call Return() even though we're about to override it
.WhenCalled(method =>
{
int param = (int) method.Arguments[0];
method.ReturnValue = new[] {param, param + 1, param + 2};
}));
}

[Test]
public void You_can_check_to_see_if_a_virtual_method_was_called()
{
var mockRepository = new MockRepository();
var sampleClass = mockRepository.PartialMock<SampleClass>();
sampleClass.Replay();

sampleClass.VirtualMethod("foo");

sampleClass.AssertWasCalled(s => s.VirtualMethod("foo"));
sampleClass.AssertWasCalled(s => s.VirtualMethod(Arg<string>.Is.Anything));
sampleClass.AssertWasCalled(s => s.VirtualMethod("foo"), o => o.Repeat.Once());
}

[Test]
public void You_cannot_use_AssertWasCalled_on_a_non_virtual_method()
{
var mockRepository = new MockRepository();
var sampleClass = mockRepository.PartialMock<SampleClass>();
sampleClass.Replay();

sampleClass.VoidMethod();

typeof(Exception).ShouldBeThrownBy(
() => sampleClass.AssertWasCalled(s => s.VoidMethod()));
}

[Test]
public void You_cannot_use_AssertWasNotCalled_on_a_non_virtual_method()
{
var mockRepository = new MockRepository();
var sampleClass = mockRepository.PartialMock<SampleClass>();
sampleClass.Replay();

typeof (Exception).ShouldBeThrownBy(
() => sampleClass.AssertWasNotCalled(s => s.NonVirtualMethod(1)));
}

[Test]
public void You_can_get_the_arguments_of_calls_to_a_virtual_method()
{
var mockRepository = new MockRepository();
var sampleClass = mockRepository.PartialMock<SampleClass>();
sampleClass.Replay();

sampleClass.VirtualMethod("foo");

IList<object[]> argsPerCall = sampleClass.GetArgumentsForCallsMadeOn(s => s.VirtualMethod("foo"));
argsPerCall[0][0].ShouldEqual("foo");
}

[Test]
public void You_cannot_get_the_arguments_of_calls_to_a_non_virtual_method()
{
var mockRepository = new MockRepository();
var sampleClass = mockRepository.PartialMock<SampleClass>();
sampleClass.Replay();

sampleClass.NonVirtualMethod(1);

typeof(Exception).ShouldBeThrownBy(
() => sampleClass.GetArgumentsForCallsMadeOn(s => s.NonVirtualMethod(0)));
}

[Test]
public void Non_virtual_properties_work_as_normal()
{
var mockRepository = new MockRepository();
var sampleClass = mockRepository.PartialMock<SampleClass>();
sampleClass.Replay();

sampleClass.NonVirtualProperty = "foo";
sampleClass.NonVirtualProperty.ShouldEqual("foo");
}

[Test]
public void Virtual_properties_work_as_normal()
{
var mockRepository = new MockRepository();
var sampleClass = mockRepository.PartialMock<SampleClass>();
sampleClass.Replay();

sampleClass.VirtualProperty = "foo";
sampleClass.VirtualProperty.ShouldEqual("foo");
}

[Test]
public void You_can_tell_virtual_events_on_a_partial_mock_to_fire()
{
var mockRepository = new MockRepository();
var sampleClass = mockRepository.PartialMock<SampleClass>();
sampleClass.Replay();

var eventWasHandled = false;

// attach an event handler
sampleClass.SomeVirtualEvent += (args, e) => eventWasHandled = true;

// raise the event
sampleClass.Raise(s => s.SomeVirtualEvent += null, this, EventArgs.Empty);

eventWasHandled.ShouldBeTrue();
}

[Test]
public void Non_virtual_events_work_normally()
{
var mockRepository = new MockRepository();
var sampleClass = mockRepository.PartialMock<SampleClass>();
sampleClass.Replay();

var eventWasHandled = false;

// attach an event handler
sampleClass.SomeVirtualEvent += (args, e) => eventWasHandled = true;

// raise the event
sampleClass.FireSomeVirtualEvent();

eventWasHandled.ShouldBeTrue();
}
}
绿色通道:好文要顶关注我收藏该文与我联系 Young跑跑
关注 - 0
粉丝 - 2关注博主00(请您对文章做出评价)« 上一篇:设计问题-易于测试的程序
» 下一篇:Linq(2)

posted @ 2010-05-07 21:15 Young跑跑 阅读(119) 评论(0) 编辑 收藏
注册用户登录后才能发表评论,请 登录 或 注册,返回博客园首页。
最新IT新闻:
· 我6个月的学习编程经历:从”大齿怪“到“狂欢者”
· 众多用户在 Google 搜索后得到了 404 错误
· 苹果应用商店在华屡涉侵权之争:审核管理成温床
· 腾讯"给力新政"疯传 为员工提供10亿免息房贷
· 华尔街投行之罪:赚钱第一 客户幸福感第二
» 更多新闻...
知识库最新文章:

数据库设计 Step by Step (3)
仿新浪微博返回顶部的js实现(jQuery/MooTools)
14条最佳JS代码编写技巧
项目管理杂谈-员工的积极性在哪里?
Javascript中的对象查找

» 更多知识库文章...
网站导航: 博客园首页 IT新闻 我的园子 闪存 程序员招聘 博问

China-pub 计算机图书网上专卖店!6.5万品种2-8折!
China-Pub 计算机绝版图书按需印刷服务

简洁版式:RhinoMock(2)---Stubs & MocksCopyright ©2011 Young跑跑 欢迎访问我们公司:

1.京东商城:京东商城

强大的团队,开放的空间,我得在这里加油!拐了,拐了,拐到产品经理!
---------------------------------------------------------




粉丝 - 2
关注 - 0
我的主页 个人资料
我的闪存 发短消息< 2010年5月 >

日 一 二 三 四 五 六
25 26 27 28 29 30 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

搜索

常用链接我的随笔
我的空间
我的短信
我的评论
更多链接
我的参与我的新闻最新评论我的标签
随笔分类(71).Net.2(6)
Erp.Wms系统(2)
Info.行业知识(2)
Music every day
OO.OOAD(2)
OO.UP(8)
OO.设计规范(1)
OO.设计模式(4)
OO.设计思考(9)
OO.重构(2)
OpenSource.ActiveReport(1)
OpenSource.IBatis.net(1)
OpenSource.Log4Net(7)
Web.Asp.net(2)
Web.jquery(5)
每天学习新知识总结(8)
算法.数据结构
算法.算法(2)
心(4)
知识库.Net(2)
知识库.设计(1)
知识库.数据库(2)
随笔档案(151)2011年3月 (2)
2011年2月 (1)
2010年12月 (1)
2010年9月 (3)
2010年8月 (2)
2010年7月 (11)
2010年6月 (17)
2010年5月 (12)
2010年4月 (11)
2010年3月 (3)
2010年2月 (10)
2010年1月 (4)
2009年11月 (17)
2009年10月 (29)
2009年9月 (3)
2009年7月 (2)
2009年6月 (3)
2009年5月 (1)
2008年11月 (2)
2008年10月 (5)
2008年9月 (1)
2008年8月 (1)
2008年6月 (2)
2008年3月 (6)
2008年2月 (1)
2008年1月 (1)
收藏夹(177)1.开发经验(39)
2.精品(6)
3.编程理论(2)
3.分析,设计(2)
3.网站保护(1)
3.项目管理(4)
3.性能维护(3)
4.fck editor(2)
4.Silverlight(6)
4.前端技术 jquery(36)
5. .net4.0(1)
5.log4net(6)
5.后端技术收藏夹(16)
5.控件开发,扩展,使用(5)
6.wcf技术收藏夹(1)
6.wf技术收藏夹 (2)
6.winform 技术(2)
7.office develop(8)
7.数据访问-ADO.NET Entity Framework(3)
7.数据访问-IBatisNet + Castle(7)
7.数据访问-Linq(1)
8.sql server(10)
WhatInYourHeart(2)
分布式开发,查询(3)
未整理(2)
杂项(7)
CnBlogs牛人堂allenlooplee
--好文章,性能
dflying blogs
good HTMl
jeffreyzhao
jimmyZhang
牛人。
js高手
有不少js不错
justion young
good js ajax css xhtml
MSDN Code Gallery
msdn Magazine
sl--不少东西
wwf 高手
安全专家
收藏了很多文章
数据结构,算法
有一些数据结构的东西
司徒登
很全面
天轰穿
good js
侠缘
good articaldom obj
NMock
最新随笔1. 条码打印
2. 你为谁活?
3. WMS业务用语-1
4. IMEI码
5. sql检查
6. Ibatis 优化
7. Java 多线程 操作
8. sql 合并
9. ISBN 国际标准书号
10. java mulitThread
最新评论1. Re:Rhino Mock (5)使用技巧。
顶!为什么没有(3)呢
--韩飞
2. Re:Rhino Mock(1)
楼主加油啊,期待下一篇。。。
--韩飞
3. Re:Rhino Mock(1)
顶一个,学习了。
--韩飞
4. Re:羊快跑曰
看看这个,多线程咱也得深入点
--Young跑跑
5. Re:羊快跑曰
share point 是否可以帮助猪宝宝呢?
--Young跑跑
阅读排行榜1. windows 下架设svn服务器(转载+修改)(4220)
2. Web Site 与 Web Application 的区别 (部分翻译)(612)
3. jquery 控件 转帖(540)
4. (转)c# Invoke和BeginInvoke区别(492)
5. js 判断小数点(489)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值