我有一个单元测试夹具,我正在尝试在ASP.NET MVC控制器上测试一个ControllerAction,该控制器用于Web应用程序上的成员函数.我正在尝试模拟测试的HttpContext.正在测试的ControllerAction实际上设置了HttpContext的属性,例如Session值,Response.Cookies值等.这不是所有代码,但这里是我试图运行的测试的粗略示例:
[Test]
public void ValidRegistrationDataSuccessfullyCreatesAndRegistersUser()
{
var context = new Mock<HttpContextBase>() {DefaultValue = DefaultValue.Mock};
context.SetupAllProperties();
var provider = new Mock<MembershipProvider>(new object[] {context.Object});
var controller = new AccountController(context.Object, provider.Object);
// This just sets up a local FormCollection object with valid user data
// in it to use to attempt the registration
InitializeValidFormData();
ActionResult result = controller.Register(_registrationData);
Assert.IsInstanceOfType(typeof(ViewResult), result);
// Here is where I'd like to attempt to do Assertions against properties
// of the HttpContext, like ensuring that a Session …Run Code Online (Sandbox Code Playgroud) 使用Moq,我有一个非常奇怪的问题,如果我设置的方法是公共的,模拟上的设置似乎只能工作.我不知道这是一个Moq bug还是我错了(Moq的新手).以下是测试用例:
public class TestClass
{
public string Say()
{
return Hello();
}
internal virtual string Hello()
{
return "";
}
}
[TestMethod]
public void Say_WhenPublic_CallsHello()
{
Mock<TestClass> mock = new Mock<TestClass>();
mock.Setup(x => x.Hello()).Returns("Hello World");
string result = mock.Object.Say();
mock.Verify(x => x.Hello(), Times.Exactly(1));
Assert.AreEqual("Hello World", result);
}
Run Code Online (Sandbox Code Playgroud)
该消息失败了:
Say_WhenPublic_CallsHello失败:Moq.MockException:调用没有在仿1次进行的:X => x.Hello()在Moq.Mock.ThrowVerifyException(IProxyCall预期,表达表达,倍)...
如果我像这样公开Hello方法,则测试通过.这是什么问题?
public virtual string Hello()
{
return "";
}
Run Code Online (Sandbox Code Playgroud)
提前致谢!
使用Moq我Report TheReport { get; set; }在一个接口上模拟一个属性,ISessionData这样我就可以检查在这个属性上设置的值.
为了达到这个目的,我正在使用SetupGet并SetupSet如下:
// class-level fields
protected Report _sessionReport;
protected Mock<ISessionData> SessionData { get; private set; }
Run Code Online (Sandbox Code Playgroud)
在我的设置方法中......
SessionData = new Mock<ISessionData>();
SessionData
.SetupSet(s => s.TheReport = It.IsAny<Report>())
.Callback<RDLDesigner.Common.Report>(r =>
{
_sessionReport = r;
SessionData.SetupGet(s => s.TheReport).Returns(_sessionReport);
});
Run Code Online (Sandbox Code Playgroud)
我在StackOverflow上找到了这种方法并且它可以工作,但我不明白为什么.我期待SetupGet在SetupSet回调之外接听电话.
任何人都可以解释这种方法的工作方式和原因,以及它是否是模拟这种类型属性的最合适方式?
使用SessionData.SetupProperty(s => s.TheReport);也适用于我的场景,但我仍然对我的原始方法如何以及为何起作用的任何解释感兴趣.
我正在尝试使用Moq来模拟界面:
public interface IMatchSetupRepository
{
IEnumerable<MatchSetup> GetAll();
}
Run Code Online (Sandbox Code Playgroud)
我在做:
var matchSetupRepository = new Mock<IMatchSetupRepository>();
matchSetupRepository
.Setup(ms => ms.GetAll())
.Returns(null);
Run Code Online (Sandbox Code Playgroud)
但由于错误,它甚至无法编译:
错误CS0121:以下方法或属性之间的调用不明确:'Moq.Language.IReturns <Data.Contract.IMatchSetupRepository,System.Collections.Generic.IEnumerable <Data.Model.MatchSetup >>.返回(System.Collections.Generic .IEnumerable <Data.Model.MatchSetup>)'和'Moq.Language.IReturns <Data.Contract.IMatchSetupRepository,System.Collections.Generic.IEnumerable <Data.Model.MatchSetup >>.返回(System.Func <System.Collections .Generic.IEnumerable <Data.Model.MatchSetup >>)"
我正在使用:
Moq.dll,v4.0.20926
在RhinoMocks中,您可以告诉您的模拟IgnoreArguments作为一揽子声明.在Moq中,似乎必须为每个参数指定It.IsAny().但是,这不适用于ref和out参数.如何测试以下方法我需要Moq内部服务调用以返回特定结果:
public void MyMethod() {
// DoStuff
IList<SomeObject> errors = new List<SomeObject>();
var result = _service.DoSomething(ref errors, ref param1, param2);
// Do more stuff
}
Run Code Online (Sandbox Code Playgroud)
测试方法:
public void TestOfMyMethod() {
// Setup
var moqService = new Mock<IMyService>();
IList<String> errors;
var model = new MyModel();
// This returns null, presumably becuase "errors"
// here does not refer to the same object as "errors" in MyMethod
moqService.Setup(t => t.DoSomething(ref errors, ref model, It.IsAny<SomeType>()).
Returns(new OtherType()));
}
Run Code Online (Sandbox Code Playgroud)
更新:因此,将错误从"ref"更改为"out"有效.所以看起来真正的问题是有一个你不能注入的ref参数.
我已阅读本答案由Ragzitsu了同样的问题.我仍然对如何实现事情感到困惑.有人可以给我一个实现的例子.
我有以下课程:
class Fizz : IFizz
{
}
class Buzz : IBuzz
{
}
class Bar : IBar
{
}
class Foo : IFoo
{
public Foo(IBar bar, IFizz fizz, IBuzz buzz)
{
//initialize etc.
}
//public methods
}
Run Code Online (Sandbox Code Playgroud)
在这里绕过构造函数的实用方法是什么?我想做点什么
var foo = new Mock<IFoo>();
Run Code Online (Sandbox Code Playgroud)
换句话说,代码将如何看待建议
The best thing to do would be right click on your class and choose Extract interface.
我正在尝试使用Moq创建一个单元测试,测试MongoDB.AspNet.Identity V2提供程序.这条线给了我悲伤:
var appUser = new Mock<PreRegistrationMVC.Models.ApplicationUser>();
var userStore = new Mock<MongoDB.AspNet.Identity.UserStore<PreRegistrationMVC.Models.ApplicationUser>>();
Run Code Online (Sandbox Code Playgroud)
似乎userStore不会正确实例化这里是错误.
Castle.DynamicProxy.InvalidProxyConstructorArgumentsException was unhandled by user code
HResult=-2147024809
Message=Can not instantiate proxy of class: MongoDB.AspNet.Identity.UserStore`1[[MVC.Models.ApplicationUser, MVC, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].
Could not find a parameterless constructor.
Source=Moq
StackTrace:
at Castle.DynamicProxy.ProxyGenerator.CreateClassProxyInstance(Type proxyType, List`1 proxyArguments, Type classToProxy, Object[] constructorArguments)
at Castle.DynamicProxy.ProxyGenerator.CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, Object[] constructorArguments, IInterceptor[] interceptors)
at Moq.Proxy.CastleProxyFactory.CreateProxy(Type mockType, ICallInterceptor interceptor, Type[] interfaces, Object[] arguments)
at Moq.Mock`1.<InitializeInstance>b__2()
at Moq.PexProtector.Invoke(Action action)
at Moq.Mock`1.InitializeInstance()
at Moq.Mock`1.OnGetObject()
at …Run Code Online (Sandbox Code Playgroud) 我曾经有过几次这样的事情会有所帮助.例如,我有AccountCreator一个Create方法,需要一个NewAccount.我AccountCreator有一个IRepository最终将用于创建帐户.我AccountCreator将首先将属性映射NewAccount到Account,第二次传递Account到repo以最终创建它.我的测试看起来像这样:
public class when_creating_an_account
{
static Mock<IRepository> _mockedRepository;
static AccountCreator _accountCreator;
static NewAccount _newAccount;
static Account _result;
static Account _account;
Establish context = () =>
{
_mockedRepository = new Mock<IRepository>();
_accountCreator = new AccountCreator(_mockedRepository.Object);
_newAccount = new NewAccount();
_account = new Account();
_mockedRepository
.Setup(x => x.Create(Moq.It.IsAny<Account>()))
.Returns(_account);
};
Because of = () => _result = _accountCreator.Create(_newAccount);
It should_create_the_account_in_the_repository = () => _result.ShouldEqual(_account); …Run Code Online (Sandbox Code Playgroud) 假设我有一个类"ClassA",它依赖于类"ClassB"(注入到ClassA的构造函数中).我想模拟ClassB,以便我可以单独测试ClassA.这两个类都是内部的.
如果我错了,请纠正我,但看起来Moq只能模拟一个类,如果它是公共的,它有一个公共无参数构造函数,并且要模拟的方法是public virtual.我真的不想让这些课程公开可见.我错过了Moq的东西,还是不适合我想做的事情?
我想我可以创建一个ClassB实现的接口(比如"IClassB"),将其注入ClassA,然后模拟接口.ClassB仍然可以是内部的(虽然我意识到接口方法必须是公共的).虽然这可行,但我对创建大量接口感到不安,其唯一目的是支持单元测试模拟.思考?
我想测试我的类的方法A,但是没有调用通常由A调用的实际方法B.那是因为B有很多外部交互,我现在不想测试.
我可以为B调用的所有服务创建模拟,但这是相当有用的.我宁愿只是模拟B并让它返回样本数据.
这可能与Moq框架有关吗?
moq ×10
c# ×7
mocking ×4
unit-testing ×3
.net ×1
asp.net-mvc ×1
mongodb ×1
properties ×1
tdd ×1
verify ×1