vs fakeserror1935 安装程序集集是什么意思

开发工具:Visual Studio 2012
测试库:Visual Studio 2012自带的MSTest
DI框架:Unity&
数据持久层:Entity Framework
前端UI:ASP.NET MVC 4.0
需求:我这里假设只满足两个功能,一个用户注册,另一个则是登陆的功能,借助于一些DDD思想,我将从领域层(或者常说的BLL)开始开发,当然每一层都是采用TDD,按我喜欢的做法就是&接口先行,测试驱动&,不废话,直奔主题吧。
有关VS2012的单元测试请参见《》
有关测试中使用的IdleTest库请参见
一、首先来创建解决方案与项目的结构。
1.&创建空白解决方案&IdleTest.TDDEntityFramework&,新建解决方案文件夹&Interfaces&,并在文件夹内创建两个项目 &IdleTest.TDDEntityFramework.IRepositories& 和 &IdleTest.TDDEntityFramework.IServices&。
2.&直接在解决方案下创建类库项目 &IdleTest.TDDEntityFramework.Services&、&IdleTest.TDDEntityFramework.Models& 和 &IdleTest.TDDEntityFramework.Repositories&
3.&在解决方案下创建MVC4项目"IdleTest.TDDEntityFramework.MvcUI"作为最终的UI,我这里选择空模板,解决方案初始结构初始结构图如下
4.&把所有类库项目中自动生成的&Class1.cs&文件删除。
5.&使用Visio画出解决方案中各项目的关系(如下图),这图画的是项目关系,实际上这些项目内的类也都遵循这样的关系。例如本项目只有一个Model,即UserModel,那么&IdleTest.TDDEntityFramework.IRepositories&下就相应将类命名为&IUserRepository&,&IdleTest.TDDEntityFramework.IServices&对应&IUserService&,以此类推,非接口则去掉前缀&I&。这是我个人的一些习惯,每个人可能命名方式可能不太一样,这很正常,但是如果是超过一个人来共同开发,则应将规范统一,俗话说&约定优于配置&嘛。
6.&这里只是自己演练TDD的Demo而已,将不使用&UnitOfWork&,其他也可能会缺少不少功能,因为不低不在于Entity Framework或MVC等等,而关注的只是单元测试驱动开发罢了。
二、测试前的编码以及其他方面的准备
7.&在&IdleTest.TDDEntityFramework.Models&下添加类&UserModel&。
public class UserModel
public string LoginName { get; set; }
public string Password { get; set; }
public int Age { get; set; }
8.&分别在项目&IdleTest.TDDEntityFramework.IRepositories&和&IdleTest.TDDEntityFramework.IServices&下添加引用&IdleTest.TDDEntityFramework.Models&,并分别添加接口&IUserRepository&、&IRepository&和&IUserService&。&
public interface IUserRepository : IRepository&UserModel, string&
public interface IRepository&TEntity, TKey& where TEntity : class
IEnumerable&TEntity& Get(
Expression&Func&TEntity, bool&& filter = null,
Func&IQueryable&TEntity&, IOrderedQueryable&TEntity&& orderBy = null,
string includeProperties = "");
TEntity GetSingle(TKey id);
void Insert(TEntity entity);
void Update(TEntity entityToUpdate);
void Delete(TKey id);
void Delete(TEntity entityToDelete);
IRepository
public interface IUserService
bool Login(UserModel model);
bool Register(UserModel model);
UserModel GetModel(string loginName);
IUserService
  那么借助DDD的一些思想,这里的IUserService体现着功能需求,Service这层的代码完全由业务需求确定,因而IUserService只编写了三个方法。而Repository这层则不去关心业务,只是常规性的公开且提供一些方法出来,这在很多项目中几乎都是确定,孤儿IRepository也就自然而然具有了增删改查的功能了。
9.&开始涉及单元测试,创建解决方案文件夹&Tests&,并在该文件夹下创建单元测试项目&IdleTest.TDDEntityFramework.ServiceTest&,添加引 用&IdleTest.TDDEntityFramework.IRepositories&、&IdleTest.TDDEntityFramework.IServices&、&IdleTest.TDDEntityFramework.Services&、&IdleTest.TDDEntityFramework.Models&,紧接着对&IdleTest.TDDEntityFramework.IRepositories&添加&Fakes程序集&(有关Fakes可参照《》)。
10.&在解决方案物理路径下创建文件夹&libs&,并将&IdleTest&中相关dll拷贝进去。接着在项目&IdleTest.TDDEntityFramework.ServiceTest&添加引用,在&引用管理器&中单击&浏览&按钮,找到刚刚创建的&libs&文件夹,并添加下图所示引用。有关IdleTest可参照从下载编译。
三、编写单元测试,边测试边修改代码
11.&我将在刚添加的测试项目中编写一个针对&IUserService&的测试基类&BaseUserServiceTest&(关于对接口的测试可以参照《》)。
using IdleT
using IdleTest.MST
using IdleTest.TDDEntityFramework.IS
using IdleTest.TDDEntityFramework.IRepositories.F
using System.Collections.G
using System.L
using System.Linq.E
using System.T
using System.Threading.T
using IdleTest.TDDEntityFramework.M
using IdleTest.TDDEntityFramework.IR
using Microsoft.VisualStudio.TestTools.UnitT
namespace IdleTest.TDDEntityFramework.ServiceTest
public abstract class BaseUserServiceTest
protected string ExistedLoginName = "zhangsan";
protected string ExistedPassword = "123456";
protected string NotExistedLoginName = "zhangsan1";
protected string NotExistedPassword = "123";
private IUserRepository userR
protected IList&UserModel& ExistedU
protected abstract IUserService UserService
/// &summary&
/// IUserRepository模拟对象
/// &/summary&
public virtual IUserRepository UserRepository
if (this.userRepository == null)
StubIUserRepository stubUserRepository = new StubIUserRepository();
//模拟Get方法
stubUserRepository.GetExpressionOfFuncOfUserModelBooleanFuncOfIQueryableOfUserModelIOrderedQueryableOfUserModelString
= (x, y, z) =&
return this.ExistedUsers.Where&UserModel&(x.Compile());
//模拟GetSingle方法
stubUserRepository.GetSingleString = p =& this.ExistedUsers.FirstOrDefault&UserModel&(o =& o.LoginName == p);
//模拟Insert方法
stubUserRepository.InsertUserModel = (p) =& this.ExistedUsers.Add(p);
this.userRepository = stubUserR
return this.userR
[TestInitialize]
public void InitUserList()
//每次测试前都初始化
this.ExistedUsers = new List&UserModel& { new UserModel { LoginName = ExistedLoginName, Password = ExistedPassword } };
public virtual void LoginTest()
//验证登陆失败的场景
AssertCommon.AssertBoolean&UserModel&(
new UserModel[] {
null, new UserModel(),
new UserModel { LoginName = string.Empty, Password = ExistedPassword }, //账户为空
new UserModel { LoginName = ExistedLoginName, Password = string.Empty }, //密码为空
new UserModel { LoginName = ExistedLoginName, Password = NotExistedPassword }, //密码错误
new UserModel { LoginName = NotExistedLoginName, Password = NotExistedPassword },
//账户密码错误
new UserModel { LoginName = NotExistedLoginName, Password = ExistedLoginName }
//账户错误
}, false, p =& UserService.Login(p));
//账户密码正确,验证成功,这里假设正确的账户密码是"zhangsan"、"123456"
UserModel model = new UserModel { LoginName = ExistedLoginName, Password = ExistedPassword };
AssertCommon.AssertEqual&bool&(true, UserService.Login(model));
public virtual void RegisterTest()
//验证注册失败的场景
AssertCommon.AssertBoolean&UserModel&(
new UserModel[] {
null, new UserModel(),
new UserModel { LoginName = string.Empty, Password = NotExistedPassword }, //账户为空
new UserModel { LoginName = NotExistedLoginName, Password = string.Empty }, //密码为空
new UserModel { LoginName = ExistedLoginName, Password = NotExistedPassword }, //账户已存在
}, false, p =& UserService.Register(p));
//验证注册成功的场景
//密码与他人相同也可注册
UserModel register1 = new UserModel { LoginName = "register1", Password = ExistedPassword };
UserModel register2 = new UserModel { LoginName = "register2", Password = NotExistedPassword };
UserModel register3 = new UserModel { LoginName = "register3", Password = NotExistedPassword, Age = 18 };
AssertCommon.AssertBoolean&UserModel&(
new UserModel[] { register1, register2, register3 }, true, p =& UserService.Register(p));
//获取用户且应与注册的信息保持一致
UserModel actualRegister1 = UserService.GetModel(register1.LoginName);
AssertCommon.AssertEqual&string&(register1.LoginName, actualRegister1.LoginName);
AssertCommon.AssertEqual&string&(register1.Password, actualRegister1.Password);
AssertCommon.AssertEqual&int&(register1.Age, actualRegister1.Age);
UserModel actualRegister2 = UserService.GetModel(register2.LoginName);
AssertCommon.AssertEqual&string&(register2.LoginName, actualRegister2.LoginName);
AssertCommon.AssertEqual&string&(register2.Password, actualRegister2.Password);
AssertCommon.AssertEqual&int&(register2.Age, actualRegister2.Age);
UserModel actualRegister3 = UserService.GetModel(register3.LoginName);
AssertCommon.AssertEqual&string&(register3.LoginName, actualRegister3.LoginName);
AssertCommon.AssertEqual&string&(register3.Password, actualRegister3.Password);
AssertCommon.AssertEqual&int&(register3.Age, actualRegister3.Age);
public virtual void GetModelTest()
AssertCommon.AssertIsNull&string, UserModel&(TestCommon.GetEmptyStrings(), true, p =& UserService.GetModel(p));
AssertCommon.AssertIsNull(true, UserService.GetModel(NotExistedLoginName));
UserModel actual = UserService.GetModel(ExistedLoginName);
AssertCommon.AssertEqual&string&(ExistedLoginName, actual.LoginName);
AssertCommon.AssertEqual&string&(ExistedPassword, actual.Password);
BaseUserServiceTest
  BaseUserServiceTest类本身不会具有任何测试,只有子类去继承它,且实现抽象属性&UserService&、Override相应的测试方法(LoginTest、RegisterTest、GetModelTest)并声明&TestMethod&特性后才能进行测试。
12.&在测试项目再编写类UserServiceTest,继承BaseUserServiceTest。&
[TestClass]
public class UserServiceTest : BaseUserServiceTest
protected override IUserService UserService
get { return new UserService(this.UserRepository); }
[TestMethod]
public override void GetModelTest()
base.GetModelTest();
[TestMethod]
public override void LoginTest()
base.LoginTest();
[TestMethod]
public override void RegisterTest()
base.RegisterTest();
UserServiceTest
  由于父类已做好了相应的测试代码,此时编写UserServiceTest就有点一劳永逸的感觉了。
  注意在实现&UserService&属性时,编写如下图所示代码后按&Alt+Shift+F10&在弹出的小菜单中选中&为UserService生成类&回车,这时发现它生成在了我们的测试项目中,我暂时不会去理会这些,现在最要紧的是我需要在最短时间最少代码量上使得我的测试通过。
  接着去修改刚生成的UserService类。&
public class UserService : IUserService
private IUserRepository userR
public UserService(IUserRepository userRepository)
// TODO: Complete member initialization
this.userRepository = userR
public bool Login(UserModel model)
throw new NotImplementedException();
public bool Register(UserModel model)
throw new NotImplementedException();
public UserModel GetModel(string loginName)
throw new NotImplementedException();
UserService
13.&生成之后打开&测试资源管理器&稍等几秒即可发现三个需要测试的方法呈现了。此时测试当然都是全部不通过。继续往下修改UserService,直至测试通过。
public class UserService : IUserService
private IUserRepository userR
public UserService(IUserRepository userRepository)
// TODO: Complete member initialization
this.userRepository = userR
#region IUserService成员
public bool Login(UserModel model)
if (!IsValidModel(model))
return false;
IList&UserModel& list =
userRepository.Get(p =& p.LoginName == model.LoginName && p.Password == model.Password).ToList();
return list != null && list.Count & 0;
public bool Register(UserModel model)
if (!IsValidModel(model))
return false;
if (GetModel(model.LoginName) != null)
return false;
userRepository.Insert(model);
return true;
public UserModel GetModel(string loginName)
if (!string.IsNullOrEmpty(loginName))
return userRepository.GetSingle(loginName);
return null;
#endregion
private bool IsValidModel(UserModel model)
return model != null && !string.IsNullOrEmpty(model.LoginName) && !string.IsNullOrEmpty(model.Password);
UserService
14.&此时测试已通过,查看代码覆盖率,双击&UserService&下未达到100%覆盖率的行(如下图所示)可以查看哪些代码尚未覆盖,然后酌情再看是否需要增加或修改代码以使覆盖率达到100%,我这里分析当前未覆盖的对项目没有什么影响,故不再修改。
15. 最后将UserService类剪切到项目&IdleTest.TDDEntityFramework.Services&,添加引用,修改相应命名空间。
再次运行测试并顺利通过,那么这一阶段的开发与单元测试均大功告成。
  上述过程简言之,就是先搭建VS解决方案的项目结构,然后编写Model(此无需测试,也是整个项目传递数据的基本),再写项目需要的接口,接着针对接口编写单元测试,
最后才是编写实现接口的类代码。
  对于实现接口的类中的一些方法(如&UserService&类的&IsValidModel&方法)我并没有针对它编写测试,首先它是一个私有方法(关于私有方法需不需要测试的争论貌似现在还没有统一的结论,鄙人能力有限,不敢妄加评价);其次即使它是一个public方法,我也仍然不会去测试它,因为它只是为&IUserService&接口成员服务的,或者说该方法原本就不需要,只是我写代码中重构出来,编写完UserService我只关心该类中的&IUserService&接口成员,所以&&
其实,这里也可以通过代码覆盖率看到,即使没有专门对&IsValidModel&方法编写相应测试,但是它的覆盖率仍然是100%,我不能确定私有方法到底要不要测试,但是在这里我不测&IsValidModel&方法肯定没有错。
  测试基类&BaseUserServiceTest&是针对&IUserService&接口编写的,而它的子类貌似什么都不做,我之所以这么写,只是为了以后如果有新的类实现&IUserService&接口
时,我仍然只需要简单的添加&BaseUserServiceTest&的一个子类,就可以完成测试,文中貌似也提到,有种一劳永逸的感觉,除非接口改变,否则对类的修改等等基本都不会影响
到原有测试。这样就足以保证了以后修改bug、代码重构或需求变化时对代码修改后仍能。
  由于使用了依赖注入,故而测试时就可以隔离依赖,文中Service层原本是依赖Repository,但是我这里在未具体实现Repository前都不会影响对Service层的开发与测试。
  TDD前期工作量比较大,但是对于后期代码(例如整体测试修改bug、代码重构或需求变化时对代码修改)质量的保证是非常可靠的。
  未完待续。。。。。。
阅读(...) 评论()vs fakes程序集是什么意思_百度知道
vs fakes程序集是什么意思
提问者采纳
icrosoft Fakes 是微软提供的一套可以快速进行Mock测试的框架[1] 。使用模拟我们则可以只关系我们需要测试的那部分逻辑.以方便进行单元测试,可以提供成员模拟的方法,如数据库的数据变化,接口调用导致的变化,文件、及其它资源的访问等问题,已经内置于Visual Studio 2012中。如果不使用模拟方法我们要关心很多东西
其他类似问题
程序集的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁第一资料 地图信息Microsoft Fakes Framework in Visual Studio 2012 - 推酷
Microsoft Fakes Framework in Visual Studio 2012
In Unit Testing/Test Driven Development (TDD) Isolating dependencies, sometimes referred to as “mocking objects” or “faking objects” is a norm. There are many books/articles that have been written on this topic. There are also great frameworks out there, which allow us to isolate dependencies without having to use any hand written mocks/fakes. Visual Studio 2012 new Fakes framework takes faking/mocking objects to a new level. In this article, I will explain the features of Visual Studio 2012 Fakes framework. Also please remember that, currently the Fakes framework is only available in Visual Studio Ultimate edition.
Some history behind the Fakes Framework
If you have used
before, you will find the Fakes framework has a very similar usage workflow. Moles were originally designed to support the development ofMicrosoft Pex, which is another great Unit Testing tool by Microsoft Research. Microsoft Research did not use other isolation frameworks because they wanted something powerful that could mock pretty much anything, was simple and had absolutely no overhead of using it. As you would imagine, most isolation frameworks use dynamic proxies to generated mock objects, which have some overhead of using it. Moles provided a simple type safe detour framework with very clear semantics. In a nutshell, Moles replaces any .NET method with a delegate. In VS 2012, with some improvements, Moles framework became the Microsoft Fakes framework, made available in Visual Studio 2012 Ultimate Edition.
Hard to test code
As you probably know, static methods by nature, are harder to test. A static method itself is easy to test, but the code that is calling the static methods become harder to test because it is tied into the type of the class and thus cannot be easily replaced by something else.
For example, let’s say that we want to test a piece of code that throws an exception when the current date reaches 21 st of December 2012. (Reminds me of the movie “ 2012 ” but it is not
. If you are reading this article, this date has passed already and we are all good
public static void DoomsDay()
if (DateTime.Now == new DateTime())
& throw new Exception(&Boom!&);
Let’s say I want to test this method. I want the exception to be thrown when the current date equals to 21 st of December 2012. Assuming today’s date is not 21 st of December, the test would not throw an exception. So how can we make the test to fail with the “Boom!” exception? We need to get hold of DateTime.Now property. Previously I mentioned that “replacing any .NET method with a delegate”. For example, I should be able to easily replace calls to the DateTime.Now with a delegate as below.
DateTime.Now = ()=& new DateTime();
This code cannot be compiled as in .NET DateTime.Now property cannot be assigned to a delegate. However using the new VS Fakes framework, you can replace this property with a delegate. I will revisit this example a bit later, but now let’s look at how to enable VS Fakes within your project.
Enabling Visual Studio Fakes
Enabling Fakes is about creating a fake assembly that allows you to use (fake) types that replace .NET types with delegates. In this case it is the System.dll, which wraps the mscorlib.dll that contains the DateTime object.
Once you “Add Fakes Assembly”, there are some new files/assemblies that get added to the test project as seen in Figure 2.
Note that mscorlib.4.0.0.0.Fakes assembly contains a special type called Shims . Shims are strongly typed wrapper that allows you to replace .NET types with delegates.
Using the Shim for DateTime class
We just generated the Fakes library that contain Shims and now we can look at replacing the DateTime.Now with a delegate. In here, instead of using the real DateTime.Now property, you can use the Shim DateTime as below.
[TestMethod]
public void TestMethod1()
ShimDateTime.NowGet = ()=& new DateTime();
ClassA.DoomsDay();
Notice that there is a naming convention. You need to prepend the word
“Shim” to the real .NET type and call the appropriate property that uses the delegate.
Now if I run the test, my test fails! But if you look at the exception, it failed for a different reason. The complete exception is below.
Test method FakesDemo.UnitTests.UnitTest1.TestMethod1 threw exception: Microsoft.QualityTools.Testing.Fakes.Shims.ShimInvalidOperationException: A ShimsContext must be in scope in order to register shims. Use the snippet below to fix your code.-- C#:using Microsoft.QualityTools.Testing.Fusing(ShimsContext.Create()){ // your test code using Shims here}--
The Shims require running their own context. This guarantees the level of isolation that is required by Shims, have no impact on other domains whatsoever. This means that whenever you use a Shim, you need to create a context that Shim persists and destroy the Shim when the context finishes execution. You can create the ShimContext as below.
[TestMethod]
public void TestMethod1()
using(ShimsContext.Create())
& ShimDateTime.NowGet = () =& new DateTime();
&& ClassA.DoomsDay();&&&
As you see in the screenshot, we hit the “Boom” exception. The ShimDateTime.NowGet replaces the real DateTime.Now value with our own DateTime value, which we have provided via the delegate.
Before we see more examples, let’s see what’s really happening under the hood. We set a breakpoint on the delegate new
DateTime (); and re-run the test. Once the breakpoint hits you should see the stack trace as below.
FakesDemo.UnitTests.dll!FakesDemo.UnitTests.UnitTest1.TestMethod1.AnonymousMethod__0() Line 16
mscorlib.dll!System.DateTime.Now.get() + 0xa9 bytes
FakesDemo.dll!FakesDemo.ClassA.DoomsDay() Line 13 + 0x8 bytes
FakesDemo.UnitTests.dll!FakesDemo.UnitTests.UnitTest1.TestMethod1() Line 17 + 0x6 bytes
[Native to Managed Transition]
Once the code executes the DateTime.Now property in mscorlib.dll, it has taken detour to an anonymous method specified by the delegate. Using .NET reflector, if we take a close look at the implementation of ShimDateTime.NowGet , you can see the ShimRunTime replaces the DateTime.Now-& Get property with the delegate, which we have set in the test method.
public static FakesDelegates.Func&DateTime& NowGet
& [ShimMethod(&get_Now&, 24)] set
&&& ShimRuntime.SetShimPublicStatic((Delegate) value,
&&&& typeof (DateTime), get_Now&,
&&&& typeof (DateTime), new Type[0]);
So far we have discussed an example of a Shim. Shims allow you to replace methods that are Static, Non-override-able, or even private methods (I called them all unfriendly) with delegates. It re-writes the code at runtime. With Shims, you can even fake the deletion of your C:\ drive without actually deleting it. You can also generate code and inject them into the system. For example, using
BehaveAsNotImplemented () method you can inject the code to throw
//Warning - Do not attempt this outside the test context
public static void DeleteC()
Directory.Delete(@&C:\TEMP&, true);
[TestMethod]
public void TestMethod2()
using (ShimsContext.Create())
& ShimDirectory.BehaveAsNotImplemented();
&& ClassB.DeleteC();
In Unit Testing, stubs provide canned answers to the System Under Test (SUT). As Martin Fowler puts it:
“ 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'. ”
The Fakes framework also has the abili these have more to do with virtual types. For example, Stubs can be used to fake virtual types such as interfaces, abstract classes, virtual methods etc. Stubs cannot be used in non-virtual context such as private, static or sealed types.
Let’s look at an example of a Stub.
System Under Test (SUT):
public interface ILogger{
bool ShouldLog();
void Log(string message);
public class ClassA
& public string GetName(ILogger logger)
&& if (logger.ShouldLog())
&&& logger.Log(&log something&);
&&& return &some name&;
&& return string.E
In order to use stubs in our test, we need to add a Fakes assembly for the library that contains the virtual type/interface. In our previous Shims example, we add the Fakes assembly for the System.dll. In this case, it is the FakesDemo.dll. You only have to do this once, and then every time when you build the application the Fakes assembly get auto generated.
Once we add a Fakes assembly, FakesDemo.Fakes.dll gets generated. This fakes assembly contains the Stub types that we can use to replace the ILogger implementation. Please see below.
[TestMethod]
public void TestMethod1()
var stubLogger = new StubILogger
& ShouldLog = () =& true
var sut = new ClassA();
var result = sut.GetName(stubLogger);
Assert.IsTrue(!string.IsNullOrEmpty(result));
StubILogger is a type that generated for you by the Fakes Framework. ShouldLog is a property delegate (Func&T&) within the StubILogger .
If you are interested in how the FakesDemo.Fakes.dll and the stub types get generated in the first place, it is done by the Microsoft.QualityTools.Testing.Fakes assembly. This assembly generates a Fakes project (i.e f.csproj) and the associated C# classes (i.e f.cs) and compiles them into a dll (i.e FakesDemo.Fakes.dll). The source code for the auto generated class and the other artefact can be found in the test project’s obj/Debug/Fakes/...
Below is a trimmed down version of the auto generated class StubILogger
namespace FakesDemo.Fakes
public partial class StubILogger
& /// &summary&Sets the stub of ILogger.ShouldLog()&/summary&
public mqttf::Microsoft.QualityTools.Testing.Fakes.FakesDelegates.Func&bool& ShouldL
& /// &summary&Sets the stub of ILogger.ShouldLog()&/summary&
& bool fd::FakesDemo.ILogger.ShouldLog()
&& mqttf::Microsoft.QualityTools.Testing.Fakes.Stubs.IStubObserver ___observer
&&& = ((mqttf::Microsoft.QualityTools.Testing.Fakes.Stubs.IStubObservable)this).InstanceO
&& if ((object)___observer != (object)null)
&&& mqttf::Microsoft.QualityTools.Testing.Fakes.FakesDelegates.Func&bool& ___currentMethod = ((fd::FakesDemo.ILogger)this).ShouldL
&&& ___observer.Enter(typeof(fd::FakesDemo.ILogger), (global::System.Delegate)___currentMethod);
&& mqttf::Microsoft.QualityTools.Testing.Fakes.FakesDelegates.Func&bool& ___sh = this.ShouldL
&& if ((object)___sh != (object)null)
&&& return ___sh.Invoke();
&&& mqttf::Microsoft.QualityTools.Testing.Fakes.Stubs.IStubBehavior ___behavior
&&&&&&&&&&&&&&&& = ((mqttf::Microsoft.QualityTools.Testing.Fakes.Stubs.IStub)this).InstanceB
&&& return ___behavior.Result&global::FakesDemo.Fakes.StubILogger, bool&(this, &FakesDemo.ILogger.ShouldLog&);
The highlighted text shows 2 important parts
& We have a public delegate/Func field ShouldLog, which can be used to replace with our own delegate.
& private FakesDemo.ILogger.ShouldLog() method, which has the implementation of the invocation of the ShouldLog delegate.
mqttf::Microsoft.QualityTools.Testing.Fakes.FakesDelegates.Func&bool& ___sh = this.ShouldL
if ((object)___sh != (object)null)
return ___sh.Invoke();
As you see above, once the ShouldLog delegate is not null, it invokes the delegate. Previously explained Shims does the same thing, but it all happens dynamically at run time.
Observers allow you to record the calls on stubs. Fakes framework ships its own observer, which allows you to record every call, every argument made in the stub. This is similar to what you have seen in standard isolation frameworks, where you would verify (i.e mock.Verify(x =& x.SomeMethod()) the interaction of a method call.
[TestMethod]
public void TestMethod1()
var stubLogger = new StubILogger {ShouldLog = () =& true};
var sut = new ClassA();
var observer = new StubObserver();
stubLogger.InstanceObserver =
sut.GetName(stubLogger);
var calls = observer.GetCalls();
If you see the debug information of the “calls” variable, you can see the following.
There are two calls have been made – ShouldLog() and Log(message). Each call has arguments (if any), stub method, stub MethodInfo, and stub method type etc.
This is valuable information if you want to verify a certain method has been called with certain parameters. Some mock frameworks allow us to verify the number of occurrence of each method call, but I could not see a similar feature in the built-in StubObserver . Also important to note that you can write your own Observer that allows you to extend additional features.
Using Shims vs. Stubs and recommendations
As I mentioned before, Shims are used mainly to test the untestable code. You find more of these code third party components that contains lots of statics, privates etc. Often this implies there is some code smell . It is recommended to use Stubs, because the virtual types are extendable, replaceable and easily testable. The other aspect is that if you see the code that is hard to test, and you have no confidence of changing code, you can use Shims to write integration type tests and refactor the code incrementally to make the code testable.
We looked at some of the features of the new Microsoft Fakes framework. The key take away is that you can replace any .NET method with a delegate using the Fakes framework. The statically typed detour framework provides some powerful features, which allow you to stub hard-to-test methods such as statics and privates.
With Shims, the detour/delegation occurs dynamically at run time. ShimContext ensures that there is no side effect by creating a new app domain for the entire test context which detour occurs.
Stubs are lightweight wrappers which allow you to stub virtual types. Fakes Framework tools auto generate necessary code and compiled into fakes dll, which you can use the stub types without having to hand craft them.
Observers are a great way to record stub interactions in the SUT (System Under Tests) and verify them within the test.
Entire Source Code for the Sample Application can be downloaded from
已发表评论数()
&&登&&&陆&&
已收藏到推刊!
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见

我要回帖

更多关于 程序集清单 的文章

 

随机推荐